• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.18
/exist-core/src/main/java/org/exist/dom/memtree/MemTreeBuilder.java
1
/*
2
 * Elemental
3
 * Copyright (C) 2024, Evolved Binary Ltd
4
 *
5
 * admin@evolvedbinary.com
6
 * https://www.evolvedbinary.com | https://www.elemental.xyz
7
 *
8
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 *
24
 * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
25
 *       The original license header is included below.
26
 *
27
 * =====================================================================
28
 *
29
 * eXist-db Open Source Native XML Database
30
 * Copyright (C) 2001 The eXist-db Authors
31
 *
32
 * info@exist-db.org
33
 * http://www.exist-db.org
34
 *
35
 * This library is free software; you can redistribute it and/or
36
 * modify it under the terms of the GNU Lesser General Public
37
 * License as published by the Free Software Foundation; either
38
 * version 2.1 of the License, or (at your option) any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
 * Lesser General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Lesser General Public
46
 * License along with this library; if not, write to the Free Software
47
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
48
 */
49
package org.exist.dom.memtree;
50

51
import org.exist.Indexer;
52
import org.exist.Namespaces;
53
import org.exist.dom.QName;
54
import org.exist.dom.persistent.NodeProxy;
55
import org.exist.xquery.Constants;
56
import org.exist.xquery.Expression;
57
import org.exist.xquery.XQueryContext;
58
import org.w3c.dom.DOMException;
59
import org.w3c.dom.Document;
60
import org.w3c.dom.Node;
61
import org.w3c.dom.NodeList;
62
import org.xml.sax.Attributes;
63

64
import javax.annotation.Nullable;
65
import javax.xml.XMLConstants;
66
import java.util.Arrays;
67

68

69
/**
70
 * Use this class to build a new in-memory DOM document.
71
 *
72
 * @author <a href="mailto:wolfgang@exist-db.org">Wolfgang</a>
73
 */
74
public class MemTreeBuilder {
75

76
    private XQueryContext context;
77
    private DocumentImpl doc;
78
    private short level = 1;
1✔
79
    private int[] prevNodeInLevel;
80
    private String defaultNamespaceURI = XMLConstants.NULL_NS_URI;
1✔
81
    private final Expression expression;
82

83
    public MemTreeBuilder() {
84
        this((Expression) null);
1✔
85
    }
1✔
86

87
    public MemTreeBuilder(final Expression expression) {
88
        this(expression, null);
1✔
89
    }
1✔
90

91
    public MemTreeBuilder(final XQueryContext context) {
92
        this(null, context);
1✔
93
    }
1✔
94

95
    public MemTreeBuilder(final Expression expression, final XQueryContext context) {
1✔
96
        this.expression = expression;
1✔
97
        this.context = context;
1✔
98
        prevNodeInLevel = new int[15];
1✔
99
        Arrays.fill(prevNodeInLevel, -1);
1✔
100
        prevNodeInLevel[0] = 0;
1✔
101
    }
1✔
102

103
    public Expression getExpression() {
104
        return expression;
×
105
    }
106

107
    public void reset(@Nullable final XQueryContext context) {
108
        this.context = context;
1✔
109
        doc = null;
1✔
110
        level = 1;
1✔
111
        prevNodeInLevel = new int[15];
1✔
112
        Arrays.fill(prevNodeInLevel, -1);
1✔
113
        prevNodeInLevel[0] = 0;
1✔
114
        defaultNamespaceURI = XMLConstants.NULL_NS_URI;
1✔
115
    }
1✔
116

117
    /**
118
     * Returns the created document object.
119
     *
120
     * @return DOCUMENT ME!
121
     */
122
    public DocumentImpl getDocument() {
123
        return doc;
1✔
124
    }
125

126

127
    public XQueryContext getContext() {
128
        return context;
×
129
    }
130

131

132
    public int getSize() {
133
        return doc.getSize();
1✔
134
    }
135

136

137
    /**
138
     * Start building the document.
139
     */
140
    public void startDocument() {
141
        this.doc = new DocumentImpl(expression, context, false);
1✔
142
    }
1✔
143

144

145
    /**
146
     * Start building the document.
147
     *
148
     * @param explicitCreation DOCUMENT ME!
149
     */
150
    public void startDocument(final boolean explicitCreation) {
151
        this.doc = new DocumentImpl(expression, context, explicitCreation);
1✔
152
    }
1✔
153

154

155
    /**
156
     * End building the document.
157
     */
158
    public void endDocument() {
159
    }
1✔
160

161

162
    /**
163
     * Create a new element.
164
     *
165
     * @param namespaceURI DOCUMENT ME!
166
     * @param localName    DOCUMENT ME!
167
     * @param qname        DOCUMENT ME!
168
     * @param attributes   DOCUMENT ME!
169
     * @return the node number of the created element
170
     */
171
    public int startElement(final String namespaceURI, String localName, final String qname, final Attributes attributes) {
172
        final int prefixIdx = qname.indexOf(':');
1✔
173

174
        String prefix = null;
1✔
175
        if (context != null && !getDefaultNamespace().equals(namespaceURI == null ? XMLConstants.NULL_NS_URI : namespaceURI)) {
1!
176
            prefix = context.getPrefixForURI(namespaceURI);
1✔
177
        }
178

179
        if (prefix == null) {
1✔
180
            prefix = (prefixIdx != Constants.STRING_NOT_FOUND) ? qname.substring(0, prefixIdx) : null;
1✔
181
        }
182

183
        if (localName.isEmpty()) {
1✔
184
            if (prefixIdx > -1) {
1!
185
                localName = qname.substring(prefixIdx + 1);
×
186
            } else {
×
187
                localName = qname;
1✔
188
            }
189
        }
190

191
        final QName qn = new QName(localName, namespaceURI, prefix);
1✔
192
        return startElement(qn, attributes);
1✔
193
    }
194

195

196
    /**
197
     * Create a new element.
198
     *
199
     * @param qname      DOCUMENT ME!
200
     * @param attributes DOCUMENT ME!
201
     * @return the node number of the created element
202
     */
203
    public int startElement(final QName qname, final Attributes attributes) {
204
        final int nodeNr = doc.addNode(Node.ELEMENT_NODE, level, qname);
1✔
205

206
        if(attributes != null) {
1✔
207

208
            // parse attributes
209
            for(int i = 0; i < attributes.getLength(); i++) {
1✔
210
                final String attrQName = attributes.getQName(i);
1✔
211

212
                // skip xmlns-attributes
213
                if(!(attrQName.startsWith(XMLConstants.XMLNS_ATTRIBUTE))) {
1✔
214
                    final int p = attrQName.indexOf(':');
1✔
215
                    final String attrNS = attributes.getURI(i);
1✔
216
                    final String attrPrefix = (p != Constants.STRING_NOT_FOUND) ? attrQName.substring(0, p) : null;
1✔
217

218
                    String attrLocalName = attributes.getLocalName(i);
1✔
219
                    if (p == Constants.STRING_NOT_FOUND && attrLocalName.isEmpty()) {
1✔
220
                        // NOTE: Attributes#getLocalName(int) can return empty string if namespace processing is not enabled
221
                        attrLocalName = attrQName;
1✔
222
                    }
223

224
                    final QName attrQn = new QName(attrLocalName, attrNS, attrPrefix);
1✔
225
                    final int type = getAttribType(attrQn, attributes.getType(i));
1✔
226
                    doc.addAttribute(nodeNr, attrQn, attributes.getValue(i), type);
1✔
227
                }
228
            }
229
        }
230

231
        // update links
232
        if((level + 1) >= prevNodeInLevel.length) {
1!
233
            final int[] t = new int[level + 2];
×
234
            System.arraycopy(prevNodeInLevel, 0, t, 0, prevNodeInLevel.length);
×
235
            prevNodeInLevel = t;
×
236
        }
237
        final int prevNr = prevNodeInLevel[level]; // TODO: remove potential ArrayIndexOutOfBoundsException
1✔
238

239
        if(prevNr > -1) {
1✔
240
            doc.next[prevNr] = nodeNr;
1✔
241
        }
242
        doc.next[nodeNr] = prevNodeInLevel[level - 1];
1✔
243
        prevNodeInLevel[level] = nodeNr;
1✔
244
        ++level;
1✔
245
        return nodeNr;
1✔
246
    }
247

248

249
    private int getAttribType(final QName qname, final String type) {
250
        if(qname.equals(Namespaces.XML_ID_QNAME) || type.equals(Indexer.ATTR_ID_TYPE)) {
1!
251
            // an xml:id attribute.
252
            return AttrImpl.ATTR_ID_TYPE;
1✔
253
        } else if(type.equals(Indexer.ATTR_IDREF_TYPE)) {
1!
254
            return AttrImpl.ATTR_IDREF_TYPE;
×
255
        } else if(type.equals(Indexer.ATTR_IDREFS_TYPE)) {
1!
256
            return AttrImpl.ATTR_IDREFS_TYPE;
×
257
        } else {
258
            return AttrImpl.ATTR_CDATA_TYPE;
1✔
259
        }
260
    }
261

262

263
    /**
264
     * Close the last element created.
265
     */
266
    public void endElement() {
267
//      System.out.println("end-element: level = " + level);
268
        prevNodeInLevel[level] = -1;
1✔
269
        --level;
1✔
270
    }
1✔
271

272

273
    public int addReferenceNode(final NodeProxy proxy) {
274
        final int lastNode = doc.getLastNode();
1✔
275

276
        if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
1✔
277

278
            if (doc.getNodeType(lastNode) == Node.TEXT_NODE && proxy.getNodeType() == Node.TEXT_NODE) {
1!
279

280
                // if the last node is a text node, we have to append the
281
                // characters to this node. XML does not allow adjacent text nodes.
282
                doc.appendChars(lastNode, proxy.getNodeValue());
1✔
283
                return lastNode;
1✔
284
            }
285

286
            if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
1!
287

288
                // check if the previous node is a reference node. if yes, check if it is a text node
289
                final int p = doc.alpha[lastNode];
1✔
290

291
                if (doc.references[p].getNodeType() == Node.TEXT_NODE && proxy.getNodeType() == Node.TEXT_NODE) {
1!
292

293
                    // found a text node reference. create a new char sequence containing
294
                    // the concatenated text of both nodes
295
                    final String s = doc.references[p].getStringValue() + proxy.getStringValue();
1✔
296
                    doc.replaceReferenceNode(lastNode, s);
1✔
297
                    return lastNode;
1✔
298
                }
299
            }
300
        }
301

302
        // check if the node is a Document Node, if so we don't add the document, but instead we add all of its children
303
        final NodeProxy[] proxies;
304
        if (proxy.getNodeType() == Node.DOCUMENT_NODE) {
1✔
305
            final org.exist.dom.persistent.DocumentImpl document = (org.exist.dom.persistent.DocumentImpl) proxy.getNode();
1✔
306
            final NodeList documentChildren = document.getChildNodes();
1✔
307
            proxies = new NodeProxy[documentChildren.getLength()];
1✔
308
            for (int i = 0; i < documentChildren.getLength(); i++) {
1✔
309
                final org.exist.dom.persistent.NodeImpl<?> child = (org.exist.dom.persistent.NodeImpl<?>) documentChildren.item(i);
1✔
310
                proxies[i] = NodeProxy.wrap(proxy.getExpression(), child);
1✔
311
            }
312

313
            // if we are at the top of the in-memory doc, copy over any doctype decl
314
            if (level == 1 && document.getDoctype() != null) {
1✔
315
                final DocumentTypeImpl documentType = new DocumentTypeImpl(document.getExpression(), doc, -1, document.getDoctype().getName(), document.getDoctype().getPublicId(), document.getDoctype().getSystemId());
1✔
316
                doc.setDoctype(documentType);
1✔
317
            }
318
        } else {
1✔
319
            proxies = new NodeProxy[1];
1✔
320
            proxies[0] = proxy;
1✔
321
        }
322

323
        // add the node proxy(s) as reference node(s)
324
        int firstProxyNodeNr = -1;
1✔
325
        for (int i = 0; i < proxies.length; i++) {
1✔
326
            final int nodeNr = doc.addNode(NodeImpl.REFERENCE_NODE, level, null);
1✔
327
            doc.addReferenceNode(nodeNr, proxies[i]);
1✔
328
            linkNode(nodeNr);
1✔
329

330
            if (firstProxyNodeNr == -1) {
1✔
331
                firstProxyNodeNr = nodeNr;
1✔
332
            }
333
        }
334
        return firstProxyNodeNr;
1✔
335
    }
336

337

338
    public int addAttribute(final QName qname, final String value) {
339
        final int lastNode = doc.getLastNode();
1✔
340

341
        //if(0 < lastNode && doc.nodeKind[lastNode] != Node.ELEMENT_NODE) {
342
        //Definitely wrong !
343
        //lastNode = characters(value);
344
        //} else {
345
        //lastNode = doc.addAttribute(lastNode, qname, value);
346
        //}
347
        final int nodeNr = doc.addAttribute(lastNode, qname, value, getAttribType(qname, Indexer.ATTR_CDATA_TYPE));
1✔
348

349
        //TODO :
350
        //1) call linkNode(nodeNr); ?
351
        //2) is there a relationship between lastNode and nodeNr ?
352
        return nodeNr;
1✔
353
    }
354

355

356
    /**
357
     * Create a new text node.
358
     *
359
     * @param ch    DOCUMENT ME!
360
     * @param start DOCUMENT ME!
361
     * @param len   DOCUMENT ME!
362
     * @return the node number of the created node
363
     */
364
    public int characters(final char[] ch, final int start, final int len) {
365
        final int lastNode = doc.getLastNode();
1✔
366

367
        if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
1✔
368

369
            if (doc.getNodeType(lastNode) == Node.TEXT_NODE || doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE) {
1✔
370

371
                // if the last node is a Text or CDATA node, we have to append the
372
                // characters to this node. XML does not allow adjacent text nodes.
373
                doc.appendChars(lastNode, ch, start, len);
1✔
374
                return lastNode;
1✔
375
            }
376

377
            if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
1✔
378

379
                // check if the previous node is a reference node. if yes, check if it is a Text or CDATA node
380
                final int p = doc.alpha[lastNode];
1✔
381

382
                if (doc.references[p].getNodeType() == Node.TEXT_NODE || doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE) {
1!
383

384
                    // found a text node reference. create a new char sequence containing
385
                    // the concatenated text of both nodes
386
                    final StringBuilder s = new StringBuilder(doc.references[p].getStringValue());
×
387
                    s.append(ch, start, len);
×
388
                    doc.replaceReferenceNode(lastNode, s);
×
389
                    return lastNode;
×
390
                }
391
                // fall through and add the node below
392
            }
393
        }
394
        final int nodeNr = doc.addNode(Node.TEXT_NODE, level, null);
1✔
395
        doc.addChars(nodeNr, ch, start, len);
1✔
396
        linkNode(nodeNr);
1✔
397
        return nodeNr;
1✔
398
    }
399

400

401
    /**
402
     * Create a new text node.
403
     *
404
     * @param s DOCUMENT ME!
405
     * @return the node number of the created node, -1 if no node was created
406
     */
407
    public int characters(final CharSequence s) {
408
        if (s == null) {
1✔
409
            return -1;
1✔
410
        }
411

412
        final int lastNode = doc.getLastNode();
1✔
413

414
        if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
1✔
415

416
            if (doc.getNodeType(lastNode) == Node.TEXT_NODE || doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE) {
1!
417

418
                // if the last node is a Text or CDATA node, we have to append the
419
                // characters to this node. XML does not allow adjacent text nodes.
420
                doc.appendChars(lastNode, s);
1✔
421
                return lastNode;
1✔
422
            }
423

424
            if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
1✔
425

426
                final int p = doc.alpha[lastNode];
1✔
427
                // check if the previous node is a reference node. if yes, check if it is a Text or CDATA node
428

429
                if (doc.references[p].getNodeType() == Node.TEXT_NODE || doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE) {
1!
430

431
                    // found a text node reference. create a new char sequence containing
432
                    // the concatenated text of both nodes
433
                    doc.replaceReferenceNode(lastNode, doc.references[p].getStringValue() + s);
1✔
434
                    return lastNode;
1✔
435
                }
436
                // fall through and add the node below
437
            }
438
        }
439
        final int nodeNr = doc.addNode(Node.TEXT_NODE, level, null);
1✔
440
        doc.addChars(nodeNr, s);
1✔
441
        linkNode(nodeNr);
1✔
442
        return nodeNr;
1✔
443
    }
444

445

446
    public int comment(final CharSequence data) {
447
        final int nodeNr = doc.addNode(Node.COMMENT_NODE, level, null);
1✔
448
        doc.addChars(nodeNr, data);
1✔
449
        linkNode(nodeNr);
1✔
450
        return nodeNr;
1✔
451
    }
452

453

454
    public int comment(final char[] ch, final int start, final int len) {
455
        final int nodeNr = doc.addNode(Node.COMMENT_NODE, level, null);
1✔
456
        doc.addChars(nodeNr, ch, start, len);
1✔
457
        linkNode(nodeNr);
1✔
458
        return nodeNr;
1✔
459
    }
460

461

462
    public int cdataSection(final CharSequence data) {
463
        final int lastNode = doc.getLastNode();
1✔
464

465
        if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
1!
466

467
            if (doc.getNodeType(lastNode) == Node.TEXT_NODE || doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE) {
×
468

469
                // if the last node is a text node, we have to append the
470
                // characters to this node. XML does not allow adjacent text nodes.
471
                doc.appendChars(lastNode, data);
×
472
                return lastNode;
×
473
            }
474

475
            if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
×
476

477
                // check if the previous node is a reference node. if yes, check if it is a text node
478
                final int p = doc.alpha[lastNode];
×
479

480
                if (doc.references[p].getNodeType() == Node.TEXT_NODE || doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE) {
×
481

482
                    // found a text node reference. create a new char sequence containing
483
                    // the concatenated text of both nodes
484
                    doc.replaceReferenceNode(lastNode, doc.references[p].getStringValue() + data);
×
485
                    return lastNode;
×
486
                }
487
                // fall through and add the node below
488
            }
489
        }
490
        final int nodeNr = doc.addNode(Node.CDATA_SECTION_NODE, level, null);
1✔
491
        doc.addChars(nodeNr, data);
1✔
492
        linkNode(nodeNr);
1✔
493
        return nodeNr;
1✔
494
    }
495

496

497
    public int processingInstruction(final String target, final String data) {
498
        final QName qname = new QName(target, null, null);
1✔
499
        final int nodeNr = doc.addNode(Node.PROCESSING_INSTRUCTION_NODE, level, qname);
1✔
500
        doc.addChars(nodeNr, (data == null) ? "" : data);
1✔
501
        linkNode(nodeNr);
1✔
502
        return nodeNr;
1✔
503
    }
504

505
    public int namespaceNode(final String prefix, final String uri) {
506
        final QName qname;
507
        if(prefix == null || prefix.isEmpty()) {
1✔
508
            qname = new QName(XMLConstants.XMLNS_ATTRIBUTE, uri);
1✔
509
        } else {
1✔
510
            qname = new QName(prefix, uri, XMLConstants.XMLNS_ATTRIBUTE);
1✔
511
        }
512
        return namespaceNode(qname);
1✔
513
    }
514

515
    public int namespaceNode(final QName qname) {
516
        return namespaceNode(qname, false);
1✔
517
    }
518

519
    public int namespaceNode(final QName qname, final boolean checkNS) {
520
        final int lastNode = doc.getLastNode();
1✔
521
        boolean addNode = true;
1✔
522
        if(doc.nodeName != null) {
1✔
523
            final QName elemQN = doc.nodeName[lastNode];
1✔
524
            if(elemQN != null) {
1✔
525
                final String elemPrefix = (elemQN.getPrefix() == null) ? XMLConstants.DEFAULT_NS_PREFIX : elemQN.getPrefix();
1✔
526
                final String elemNs = (elemQN.getNamespaceURI() == null) ? XMLConstants.NULL_NS_URI : elemQN.getNamespaceURI();
1!
527
                final String qnPrefix = (qname.getPrefix() == null) ? XMLConstants.DEFAULT_NS_PREFIX : qname.getPrefix();
1✔
528
                if (checkNS
1!
529
                    && XMLConstants.DEFAULT_NS_PREFIX.equals(elemPrefix)
×
530
                    && XMLConstants.NULL_NS_URI.equals(elemNs)
×
531
                    && XMLConstants.DEFAULT_NS_PREFIX.equals(qnPrefix)
×
532
                    && XMLConstants.XMLNS_ATTRIBUTE.equals(qname.getLocalPart())) {
×
533

534
                    throw new DOMException(
×
535
                        DOMException.NAMESPACE_ERR,
×
536
                        "Cannot output a namespace node for the default namespace when the element is in no namespace."
×
537
                    );
538
                }
539
                if(elemPrefix.equals(qname.getLocalPart()) && (elemQN.getNamespaceURI() != null)) {
1!
540
                    addNode = false;
1✔
541
                }
542
            }
543
        }
544
        return (addNode ? doc.addNamespace(lastNode, qname) : -1);
1✔
545
    }
546

547

548
    public int documentType(final String publicId, final String systemId) {
549
//      int nodeNr = doc.addNode(Node.DOCUMENT_TYPE_NODE, level, null);
550
//      doc.addChars(nodeNr, data);
551
//      linkNode(nodeNr);
552
//      return nodeNr;
553
        return -1;
×
554
    }
555

556

557
    public void documentType(final String name, final String publicId, final String systemId) {
558
    }
×
559

560

561
    private void linkNode(final int nodeNr) {
562
        final int prevNr = prevNodeInLevel[level];
1✔
563

564
        if(prevNr > -1) {
1✔
565
            doc.next[prevNr] = nodeNr;
1✔
566
        }
567
        doc.next[nodeNr] = prevNodeInLevel[level - 1];
1✔
568
        prevNodeInLevel[level] = nodeNr;
1✔
569
    }
1✔
570

571

572
    public void setReplaceAttributeFlag(final boolean replaceAttribute) {
573
        doc.replaceAttribute = replaceAttribute;
1✔
574
    }
1✔
575

576
    public void setDefaultNamespace(final String defaultNamespaceURI) {
577
        this.defaultNamespaceURI = defaultNamespaceURI;
1✔
578
    }
1✔
579

580
    private String getDefaultNamespace() {
581
        // guard against someone setting null as the defaultNamespaceURI
582
        return defaultNamespaceURI == null ? XMLConstants.NULL_NS_URI : defaultNamespaceURI;
1!
583
    }
584
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc