1:
37:
38: package ;
39:
40: import ;
41: import ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69:
70:
82: public class DomDocument
83: extends DomNode
84: implements Document, DocumentTraversal, XPathEvaluator
85: {
86:
87: private final DOMImplementation implementation;
88: private boolean checkingCharacters = true;
89: boolean checkingWellformedness = true;
90:
91: boolean building;
92:
93: DomDocumentConfiguration config;
94:
95: String inputEncoding;
96: String encoding;
97: String version = "1.0";
98: boolean standalone;
99: String systemId;
100:
101:
113: public DomDocument()
114: {
115: this(new DomImpl());
116: }
117:
118:
127: protected DomDocument(DOMImplementation impl)
128: {
129: super(DOCUMENT_NODE, null);
130: implementation = impl;
131: }
132:
133:
137: public void setBuilding(boolean flag)
138: {
139: building = flag;
140: }
141:
142:
147: public void setCheckWellformedness(boolean flag)
148: {
149: checkingWellformedness = flag;
150: }
151:
152:
156: final public String getNodeName()
157: {
158: return "#document";
159: }
160:
161:
165: final public Element getDocumentElement()
166: {
167: for (DomNode ctx = first; ctx != null; ctx = ctx.next)
168: {
169: if (ctx.nodeType == ELEMENT_NODE)
170: {
171: return (Element) ctx;
172: }
173: }
174: return null;
175: }
176:
177:
181: final public DocumentType getDoctype()
182: {
183: for (DomNode ctx = first; ctx != null; ctx = ctx.next)
184: {
185: if (ctx.nodeType == DOCUMENT_TYPE_NODE)
186: {
187: return (DocumentType) ctx;
188: }
189: }
190: return null;
191: }
192:
193:
197: final public DOMImplementation getImplementation()
198: {
199: return implementation;
200: }
201:
202:
211: public Element getElementById(String id)
212: {
213: if (id == null || id.length() == 0)
214: {
215: return null;
216: }
217: DomDoctype doctype = (DomDoctype) getDoctype();
218: if (doctype != null && !doctype.hasIds())
219: {
220: doctype = null;
221: }
222:
223:
224:
225: Node current = getDocumentElement();
226: Node temp;
227:
228: if (current == null)
229: {
230: return null;
231: }
232: while (current != this)
233: {
234:
235: if (current.getNodeType() == ELEMENT_NODE)
236: {
237: DomElement element = (DomElement) current;
238: if (doctype != null)
239: {
240: DTDElementTypeInfo info =
241: doctype.getElementTypeInfo(current.getNodeName());
242: if (info != null &&
243: id.equals(element.getAttribute(info.idAttrName)))
244: {
245: return element;
246: }
247: else if (element.userIdAttrs != null)
248: {
249: for (Iterator i = element.userIdAttrs.iterator();
250: i.hasNext(); )
251: {
252: Node idAttr = (Node) i.next();
253: if (id.equals(idAttr.getNodeValue()))
254: {
255: return element;
256: }
257: }
258: }
259: }
260:
261: String xmlId = element.getAttribute("xml:id");
262: if (xmlId == null)
263: {
264: xmlId = element.getAttributeNS(XMLConstants.XML_NS_URI,
265: "id");
266: }
267: if (id.equals(xmlId))
268: {
269: return element;
270: }
271: }
272:
273:
274: if (current.hasChildNodes())
275: {
276: current = current.getFirstChild();
277: continue;
278: }
279:
280:
281: temp = current.getNextSibling();
282: if (temp != null)
283: {
284: current = temp;
285: continue;
286: }
287:
288:
289: do
290: {
291: temp = current.getParentNode();
292: if (temp == null)
293: {
294: return null;
295: }
296: current = temp;
297: temp = current.getNextSibling();
298: }
299: while (temp == null);
300: current = temp;
301: }
302: return null;
303: }
304:
305: private void checkNewChild(Node newChild)
306: {
307: if (newChild.getNodeType() == ELEMENT_NODE
308: && getDocumentElement() != null)
309: {
310: throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
311: "document element already present: " +
312: getDocumentElement(), newChild, 0);
313: }
314: if (newChild.getNodeType() == DOCUMENT_TYPE_NODE
315: && getDoctype() != null)
316: {
317: throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
318: "document type already present: " +
319: getDoctype(), newChild, 0);
320: }
321: }
322:
323:
329: public Node appendChild(Node newChild)
330: {
331: if (checkingWellformedness)
332: {
333: checkNewChild(newChild);
334: }
335: return super.appendChild(newChild);
336: }
337:
338:
344: public Node insertBefore(Node newChild, Node refChild)
345: {
346: if (checkingWellformedness)
347: {
348: checkNewChild(newChild);
349: }
350: return super.insertBefore(newChild, refChild);
351: }
352:
353:
359: public Node replaceChild(Node newChild, Node refChild)
360: {
361: if (checkingWellformedness &&
362: ((newChild.getNodeType() == ELEMENT_NODE &&
363: refChild.getNodeType() != ELEMENT_NODE) ||
364: (newChild.getNodeType() == DOCUMENT_TYPE_NODE &&
365: refChild.getNodeType() != DOCUMENT_TYPE_NODE)))
366: {
367: checkNewChild(newChild);
368: }
369: return super.replaceChild(newChild, refChild);
370: }
371:
372:
373:
374:
375:
376:
377:
378:
384: public static void verifyXmlName(String name)
385: {
386:
387: checkName(name, false);
388: }
389:
390: static void checkName(String name, boolean xml11)
391: {
392: if (name == null)
393: {
394: throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
395: }
396: int len = name.length();
397: if (len == 0)
398: {
399: throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
400: }
401:
402:
403:
404:
405: char c = name.charAt(0);
406: if (xml11)
407: {
408:
409: if ((c < 0x0041 || c > 0x005a) &&
410: (c < 0x0061 || c > 0x007a) &&
411: c != ':' && c != '_' &&
412: (c < 0x00c0 || c > 0x00d6) &&
413: (c < 0x00d8 || c > 0x00f6) &&
414: (c < 0x00f8 || c > 0x02ff) &&
415: (c < 0x0370 || c > 0x037d) &&
416: (c < 0x037f || c > 0x1fff) &&
417: (c < 0x200c || c > 0x200d) &&
418: (c < 0x2070 || c > 0x218f) &&
419: (c < 0x2c00 || c > 0x2fef) &&
420: (c < 0x3001 || c > 0xd7ff) &&
421: (c < 0xf900 || c > 0xfdcf) &&
422: (c < 0xfdf0 || c > 0xfffd) &&
423: (c < 0x10000 || c > 0xeffff))
424: {
425: throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
426: name, null, c);
427: }
428: }
429: else
430: {
431:
432: int type = Character.getType(c);
433: switch (type)
434: {
435: case Character.LOWERCASE_LETTER:
436: case Character.UPPERCASE_LETTER:
437: case Character.OTHER_LETTER:
438: case Character.TITLECASE_LETTER:
439: case Character.LETTER_NUMBER:
440: if ((c > 0xf900 && c < 0xfffe) ||
441: (c >= 0x20dd && c <= 0x20e0))
442: {
443:
444: throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
445: name, null, c);
446: }
447: break;
448: default:
449: if (c != ':' && c != '_' && (c < 0x02bb || c > 0x02c1) &&
450: c != 0x0559 && c != 0x06e5 && c != 0x06e6)
451: {
452: throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
453: name, null, c);
454: }
455: }
456: }
457:
458:
459: for (int i = 1; i < len; i++)
460: {
461: c = name.charAt(i);
462: if (xml11)
463: {
464:
465: if ((c < 0x0041 || c > 0x005a) &&
466: (c < 0x0061 || c > 0x007a) &&
467: (c < 0x0030 || c > 0x0039) &&
468: c != ':' && c != '_' && c != '-' && c != '.' &&
469: (c < 0x00c0 || c > 0x00d6) &&
470: (c < 0x00d8 || c > 0x00f6) &&
471: (c < 0x00f8 || c > 0x02ff) &&
472: (c < 0x0370 || c > 0x037d) &&
473: (c < 0x037f || c > 0x1fff) &&
474: (c < 0x200c || c > 0x200d) &&
475: (c < 0x2070 || c > 0x218f) &&
476: (c < 0x2c00 || c > 0x2fef) &&
477: (c < 0x3001 || c > 0xd7ff) &&
478: (c < 0xf900 || c > 0xfdcf) &&
479: (c < 0xfdf0 || c > 0xfffd) &&
480: (c < 0x10000 || c > 0xeffff) &&
481: c != 0x00b7 &&
482: (c < 0x0300 || c > 0x036f) &&
483: (c < 0x203f || c > 0x2040))
484: {
485: throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, name,
486: null, c);
487: }
488: }
489: else
490: {
491:
492: int type = Character.getType(c);
493: switch (type)
494: {
495: case Character.LOWERCASE_LETTER:
496: case Character.UPPERCASE_LETTER:
497: case Character.DECIMAL_DIGIT_NUMBER:
498: case Character.OTHER_LETTER:
499: case Character.TITLECASE_LETTER:
500: case Character.LETTER_NUMBER:
501: case Character.COMBINING_SPACING_MARK:
502: case Character.ENCLOSING_MARK:
503: case Character.NON_SPACING_MARK:
504: case Character.MODIFIER_LETTER:
505: if ((c > 0xf900 && c < 0xfffe) ||
506: (c >= 0x20dd && c <= 0x20e0))
507: {
508:
509: throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
510: name, null, c);
511: }
512: break;
513: default:
514: if (c != '-' && c != '.' && c != ':' && c != '_' &&
515: c != 0x0387 && (c < 0x02bb || c > 0x02c1) &&
516: c != 0x0559 && c != 0x06e5 && c != 0x06e6 && c != 0x00b7)
517: {
518: throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
519: name, null, c);
520: }
521: }
522: }
523: }
524:
525:
526:
527:
528: }
529:
530:
531: static void checkNCName(String name, boolean xml11)
532: {
533: checkName(name, xml11);
534: int len = name.length();
535: int index = name.indexOf(':');
536: if (index != -1)
537: {
538: if (index == 0 || index == (len - 1) ||
539: name.lastIndexOf(':') != index)
540: {
541: throw new DomDOMException(DOMException.NAMESPACE_ERR,
542: name, null, 0);
543: }
544: }
545: }
546:
547:
548: static void checkChar(String value, boolean xml11)
549: {
550: char[] chars = value.toCharArray();
551: checkChar(chars, 0, chars.length, xml11);
552: }
553:
554: static void checkChar(char[] buf, int off, int len, boolean xml11)
555: {
556: for (int i = 0; i < len; i++)
557: {
558: char c = buf[i];
559:
560:
561: if ((c >= 0x0020 && c <= 0xd7ff) ||
562: (c == 0x000a || c == 0x000d || c == 0x0009) ||
563: (c >= 0xe000 && c <= 0xfffd) ||
564: (c >= 0x10000 && c <= 0x10ffff))
565: {
566: continue;
567: }
568: if (xml11)
569: {
570: if ((c >= 0x0001 && c <= 0x001f) ||
571: (c >= 0x007f && c <= 0x0084) ||
572: (c >= 0x0086 && c <= 0x009f))
573: {
574: continue;
575: }
576: }
577: throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
578: new String(buf, off, len), null, c);
579: }
580: }
581:
582:
586: public Element createElement(String name)
587: {
588: Element element;
589:
590: if (checkingCharacters)
591: {
592: checkName(name, "1.1".equals(version));
593: }
594: if (name.startsWith("xml:"))
595: {
596: element = createElementNS(null, name);
597: }
598: else
599: {
600: DomElement domElement = new DomElement(this, null, name);
601: domElement.localName = null;
602: element = domElement;
603: }
604: defaultAttributes(element, name);
605: return element;
606: }
607:
608:
613: public Element createElementNS(String namespaceURI, String name)
614: {
615: if (checkingCharacters)
616: {
617: checkNCName(name, "1.1".equals(version));
618: }
619:
620: if ("".equals(namespaceURI))
621: {
622: namespaceURI = null;
623: }
624: if (name.startsWith("xml:"))
625: {
626: if (namespaceURI != null
627: && !XMLConstants.XML_NS_URI.equals(namespaceURI))
628: {
629: throw new DomDOMException(DOMException.NAMESPACE_ERR,
630: "xml namespace is always " +
631: XMLConstants.XML_NS_URI, this, 0);
632: }
633: namespaceURI = XMLConstants.XML_NS_URI;
634: }
635: else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
636: name.startsWith("xmlns:"))
637: {
638: throw new DomDOMException(DOMException.NAMESPACE_ERR,
639: "xmlns is reserved", this, 0);
640: }
641: else if (namespaceURI == null && name.indexOf(':') != -1)
642: {
643: throw new DomDOMException(DOMException.NAMESPACE_ERR,
644: "prefixed name '" + name +
645: "' needs a URI", this, 0);
646: }
647:
648: Element element = new DomElement(this, namespaceURI, name);
649: defaultAttributes(element, name);
650: return element;
651: }
652:
653: private void defaultAttributes(Element element, String name)
654: {
655: DomDoctype doctype = (DomDoctype) getDoctype();
656: if (doctype == null)
657: {
658: return;
659: }
660:
661:
662: DTDElementTypeInfo info = doctype.getElementTypeInfo(name);
663: if (info != null)
664: {
665: for (Iterator i = info.attributes(); i != null && i.hasNext(); )
666: {
667: DTDAttributeTypeInfo attr = (DTDAttributeTypeInfo) i.next();
668: DomAttr node = (DomAttr) createAttribute(attr.name);
669:
670: String value = attr.value;
671: if (value == null)
672: {
673: value = "";
674: }
675: node.setValue(value);
676: node.setSpecified(false);
677: element.setAttributeNode(node);
678: }
679: }
680: }
681:
682:
686: public DocumentFragment createDocumentFragment()
687: {
688: return new DomDocumentFragment(this);
689: }
690:
691:
695: public Text createTextNode(String value)
696: {
697: if (checkingCharacters)
698: {
699: checkChar(value, "1.1".equals(version));
700: }
701: return new DomText(this, value);
702: }
703:
704:
707: public Text createTextNode(char[] buf, int off, int len)
708: {
709: if (checkingCharacters)
710: {
711: checkChar(buf, off, len, "1.1".equals(version));
712: }
713: return new DomText(this, buf, off, len);
714: }
715:
716:
720: public Comment createComment(String value)
721: {
722: if (checkingCharacters)
723: {
724: checkChar(value, "1.1".equals(version));
725: }
726: return new DomComment(this, value);
727: }
728:
729:
733: public CDATASection createCDATASection(String value)
734: {
735: if (checkingCharacters)
736: {
737: checkChar(value, "1.1".equals(version));
738: }
739: return new DomCDATASection(this, value);
740: }
741:
742:
745: public CDATASection createCDATASection(char[] buf, int off, int len)
746: {
747: if (checkingCharacters)
748: {
749: checkChar(buf, off, len, "1.1".equals(version));
750: }
751: return new DomCDATASection(this, buf, off, len);
752: }
753:
754:
758: public ProcessingInstruction createProcessingInstruction(String target,
759: String data)
760: {
761: if (checkingCharacters)
762: {
763: boolean xml11 = "1.1".equals(version);
764: checkName(target, xml11);
765: if ("xml".equalsIgnoreCase(target))
766: {
767: throw new DomDOMException(DOMException.SYNTAX_ERR,
768: "illegal PI target name",
769: this, 0);
770: }
771: checkChar(data, xml11);
772: }
773: return new DomProcessingInstruction(this, target, data);
774: }
775:
776:
780: public Attr createAttribute(String name)
781: {
782: if (checkingCharacters)
783: {
784: checkName(name, "1.1".equals(version));
785: }
786: if (name.startsWith("xml:"))
787: {
788: return createAttributeNS(XMLConstants.XML_NS_URI, name);
789: }
790: else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
791: name.startsWith("xmlns:"))
792: {
793: return createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, name);
794: }
795: else
796: {
797: DomAttr ret = new DomAttr(this, null, name);
798: ret.localName = null;
799: return ret;
800: }
801: }
802:
803:
808: public Attr createAttributeNS(String namespaceURI, String name)
809: {
810: if (checkingCharacters)
811: {
812: checkNCName(name, "1.1".equals(version));
813: }
814:
815: if ("".equals(namespaceURI))
816: {
817: namespaceURI = null;
818: }
819: if (name.startsWith ("xml:"))
820: {
821: if (namespaceURI == null)
822: {
823: namespaceURI = XMLConstants.XML_NS_URI;
824: }
825: else if (!XMLConstants.XML_NS_URI.equals(namespaceURI))
826: {
827: throw new DomDOMException(DOMException.NAMESPACE_ERR,
828: "xml namespace is always " +
829: XMLConstants.XML_NS_URI,
830: this, 0);
831: }
832: }
833: else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
834: name.startsWith("xmlns:"))
835: {
836: if (namespaceURI == null)
837: {
838: namespaceURI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
839: }
840: else if (!XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
841: {
842: throw new DomDOMException(DOMException.NAMESPACE_ERR,
843: "xmlns namespace must be " +
844: XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
845: this, 0);
846: }
847: }
848: else if (namespaceURI == null && name.indexOf(':') != -1)
849: {
850: throw new DomDOMException(DOMException.NAMESPACE_ERR,
851: "prefixed name needs a URI: " + name, this, 0);
852: }
853: return new DomAttr(this, namespaceURI, name);
854: }
855:
856:
864: public EntityReference createEntityReference(String name)
865: {
866: DomEntityReference ret = new DomEntityReference(this, name);
867: DocumentType doctype = getDoctype();
868: if (doctype != null)
869: {
870: DomEntity ent = (DomEntity) doctype.getEntities().getNamedItem(name);
871: if (ent != null)
872: {
873: for (DomNode ctx = ent.first; ctx != null; ctx = ctx.next)
874: {
875: ret.appendChild(ctx.cloneNode(true));
876: }
877: }
878: }
879: ret.makeReadonly();
880: return ret;
881: }
882:
883:
899: public Node importNode(Node src, boolean deep)
900: {
901: Node dst = null;
902: switch (src.getNodeType())
903: {
904: case TEXT_NODE:
905: dst = createTextNode(src.getNodeValue());
906: break;
907: case CDATA_SECTION_NODE:
908: dst = createCDATASection(src.getNodeValue());
909: break;
910: case COMMENT_NODE:
911: dst = createComment(src.getNodeValue());
912: break;
913: case PROCESSING_INSTRUCTION_NODE:
914: dst = createProcessingInstruction(src.getNodeName(),
915: src.getNodeValue());
916: break;
917: case NOTATION_NODE:
918:
919:
920: Notation notation = (Notation) src;
921: dst = new DomNotation(this, notation.getNodeName(),
922: notation.getPublicId(),
923: notation.getSystemId());
924: break;
925: case ENTITY_NODE:
926:
927:
928: Entity entity = (Entity) src;
929: dst = new DomEntity(this, entity.getNodeName(),
930: entity.getPublicId(),
931: entity.getSystemId(),
932: entity.getNotationName());
933: if (deep)
934: {
935: for (Node ctx = src.getFirstChild(); ctx != null;
936: ctx = ctx.getNextSibling())
937: {
938: dst.appendChild(importNode(ctx, deep));
939: }
940: }
941: break;
942: case ENTITY_REFERENCE_NODE:
943: dst = createEntityReference(src.getNodeName());
944: break;
945: case DOCUMENT_FRAGMENT_NODE:
946: dst = new DomDocumentFragment(this);
947: if (deep)
948: {
949: for (Node ctx = src.getFirstChild(); ctx != null;
950: ctx = ctx.getNextSibling())
951: {
952: dst.appendChild(importNode(ctx, deep));
953: }
954: }
955: break;
956: case ATTRIBUTE_NODE:
957: String attr_nsuri = src.getNamespaceURI();
958: if (attr_nsuri != null)
959: {
960: dst = createAttributeNS(attr_nsuri, src.getNodeName());
961: }
962: else
963: {
964: dst = createAttribute(src.getNodeName());
965: }
966:
967: for (Node ctx = src.getFirstChild(); ctx != null;
968: ctx = ctx.getNextSibling())
969: {
970: dst.appendChild(importNode(ctx, false));
971: }
972: break;
973: case ELEMENT_NODE:
974: String elem_nsuri = src.getNamespaceURI();
975: if (elem_nsuri != null)
976: {
977: dst = createElementNS(elem_nsuri, src.getNodeName());
978: }
979: else
980: {
981: dst = createElement(src.getNodeName());
982: }
983: NamedNodeMap srcAttrs = src.getAttributes();
984: NamedNodeMap dstAttrs = dst.getAttributes();
985: int len = srcAttrs.getLength();
986: for (int i = 0; i < len; i++)
987: {
988: Attr a = (Attr) srcAttrs.item(i);
989: Attr dflt;
990:
991:
992: dflt = (Attr) dstAttrs.getNamedItem(a.getNodeName());
993: if (dflt != null)
994: {
995: String newval = a.getNodeValue();
996: if (!dflt.getNodeValue().equals(newval)
997: || a.getSpecified () == true)
998: {
999: dflt.setNodeValue (newval);
1000: }
1001: continue;
1002: }
1003:
1004: dstAttrs.setNamedItem((Attr) importNode(a, false));
1005: }
1006: if (deep)
1007: {
1008: for (Node ctx = src.getFirstChild(); ctx != null;
1009: ctx = ctx.getNextSibling())
1010: {
1011: dst.appendChild(importNode(ctx, true));
1012: }
1013: }
1014: break;
1015:
1016: case DOCUMENT_NODE:
1017: case DOCUMENT_TYPE_NODE:
1018:
1019:
1020: default:
1021: throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, src, 0);
1022: }
1023:
1024:
1025:
1026:
1027: if (src instanceof DomNode)
1028: {
1029: ((DomNode) src).notifyUserDataHandlers(UserDataHandler.NODE_IMPORTED,
1030: src, dst);
1031: }
1032: return dst;
1033: }
1034:
1035:
1042: public NodeIterator createNodeIterator(Node root,
1043: int whatToShow,
1044: NodeFilter filter,
1045: boolean expandEntities)
1046: {
1047: return new DomNodeIterator(root, whatToShow, filter, expandEntities,
1048: false);
1049: }
1050:
1051: public TreeWalker createTreeWalker(Node root,
1052: int whatToShow,
1053: NodeFilter filter,
1054: boolean expandEntities)
1055: {
1056: return new DomNodeIterator(root, whatToShow, filter, expandEntities,
1057: true);
1058: }
1059:
1060:
1061:
1062:
1065: public String getInputEncoding()
1066: {
1067: return inputEncoding;
1068: }
1069:
1070: public void setInputEncoding(String inputEncoding)
1071: {
1072: this.inputEncoding = inputEncoding;
1073: }
1074:
1075:
1078: public String getXmlEncoding()
1079: {
1080: return encoding;
1081: }
1082:
1083: public void setXmlEncoding(String encoding)
1084: {
1085: this.encoding = encoding;
1086: }
1087:
1088: public boolean getXmlStandalone()
1089: {
1090: return standalone;
1091: }
1092:
1093: public void setXmlStandalone(boolean xmlStandalone)
1094: {
1095: standalone = xmlStandalone;
1096: }
1097:
1098: public String getXmlVersion()
1099: {
1100: return version;
1101: }
1102:
1103: public void setXmlVersion(String xmlVersion)
1104: {
1105: if (xmlVersion == null)
1106: {
1107: xmlVersion = "1.0";
1108: }
1109: if ("1.0".equals(xmlVersion) ||
1110: "1.1".equals(xmlVersion))
1111: {
1112: version = xmlVersion;
1113: }
1114: else
1115: {
1116: throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
1117: }
1118: }
1119:
1120: public boolean getStrictErrorChecking()
1121: {
1122: return checkingCharacters;
1123: }
1124:
1125: public void setStrictErrorChecking(boolean strictErrorChecking)
1126: {
1127: checkingCharacters = strictErrorChecking;
1128: }
1129:
1130: public String lookupPrefix(String namespaceURI)
1131: {
1132: Node root = getDocumentElement();
1133: return (root == null) ? null : root.lookupPrefix(namespaceURI);
1134: }
1135:
1136: public boolean isDefaultNamespace(String namespaceURI)
1137: {
1138: Node root = getDocumentElement();
1139: return (root == null) ? false : root.isDefaultNamespace(namespaceURI);
1140: }
1141:
1142: public String lookupNamespaceURI(String prefix)
1143: {
1144: Node root = getDocumentElement();
1145: return (root == null) ? null : root.lookupNamespaceURI(prefix);
1146: }
1147:
1148: public String getBaseURI()
1149: {
1150: return getDocumentURI();
1151:
1164: }
1165:
1166: public String getDocumentURI()
1167: {
1168: return systemId;
1169: }
1170:
1171: public void setDocumentURI(String documentURI)
1172: {
1173: systemId = documentURI;
1174: }
1175:
1176: public Node adoptNode(Node source)
1177: {
1178: int sourceNodeType = source.getNodeType();
1179: switch (sourceNodeType)
1180: {
1181: case DOCUMENT_NODE:
1182: case DOCUMENT_TYPE_NODE:
1183: throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
1184: case ENTITY_NODE:
1185: case NOTATION_NODE:
1186: throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
1187: }
1188: if (source instanceof DomNode)
1189: {
1190:
1191: DomNode src = (DomNode) source;
1192: DomNode dst = src;
1193: if (dst.parent != null)
1194: {
1195: dst = (DomNode) dst.cloneNode(true);
1196: }
1197: dst.setOwner(this);
1198: src.notifyUserDataHandlers(UserDataHandler.NODE_ADOPTED, src, dst);
1199: return dst;
1200: }
1201: else
1202: {
1203:
1204: Node dst = null;
1205: switch (sourceNodeType)
1206: {
1207: case Node.ATTRIBUTE_NODE:
1208: {
1209: Attr src = (Attr) source;
1210: String nodeName = src.getNodeName();
1211: String localName = src.getLocalName();
1212: String namespaceUri = src.getNamespaceURI();
1213: dst = (localName == null) ?
1214: createAttribute(nodeName) :
1215: createAttributeNS(namespaceUri, nodeName);
1216: adoptChildren(src, dst);
1217: break;
1218: }
1219: case Node.CDATA_SECTION_NODE:
1220: {
1221: CDATASection src = (CDATASection) source;
1222: dst = createCDATASection(src.getData());
1223: break;
1224: }
1225: case Node.COMMENT_NODE:
1226: {
1227: Comment src = (Comment) source;
1228: dst = createComment(src.getData());
1229: break;
1230: }
1231: case Node.DOCUMENT_FRAGMENT_NODE:
1232: {
1233: DocumentFragment src = (DocumentFragment) source;
1234: dst = createDocumentFragment();
1235: adoptChildren(src, dst);
1236: break;
1237: }
1238: case Node.ELEMENT_NODE:
1239: {
1240: Element src = (Element) source;
1241: String nodeName = src.getNodeName();
1242: String localName = src.getLocalName();
1243: String namespaceUri = src.getNamespaceURI();
1244: dst = (localName == null) ?
1245: createElement(nodeName) :
1246: createElementNS(namespaceUri, nodeName);
1247: adoptAttributes(src, dst);
1248: adoptChildren(src, dst);
1249: break;
1250: }
1251: case Node.ENTITY_REFERENCE_NODE:
1252: {
1253: EntityReference src = (EntityReference) source;
1254: dst = createEntityReference(src.getNodeName());
1255: adoptChildren(src, dst);
1256: break;
1257: }
1258: case Node.PROCESSING_INSTRUCTION_NODE:
1259: {
1260: ProcessingInstruction src = (ProcessingInstruction) source;
1261: dst = createProcessingInstruction(src.getTarget(),
1262: src.getData());
1263: break;
1264: }
1265: case Node.TEXT_NODE:
1266: {
1267: Text src = (Text) source;
1268: dst = createTextNode(src.getData());
1269: break;
1270: }
1271: }
1272: return dst;
1273: }
1274: }
1275:
1276: void adoptChildren(Node src, Node dst)
1277: {
1278: Node node = src.getFirstChild();
1279: while (node != null)
1280: {
1281: Node next = node.getNextSibling();
1282: dst.appendChild(adoptNode(node));
1283: node = next;
1284: }
1285: }
1286:
1287: void adoptAttributes(Node src, Node dst)
1288: {
1289: NamedNodeMap srcAttrs = src.getAttributes();
1290: NamedNodeMap dstAttrs = dst.getAttributes();
1291: int len = srcAttrs.getLength();
1292: for (int i = 0; i < len; i++)
1293: {
1294: Node node = srcAttrs.item(i);
1295: String localName = node.getLocalName();
1296: if (localName == null)
1297: {
1298: dstAttrs.setNamedItem(adoptNode(node));
1299: }
1300: else
1301: {
1302: dstAttrs.setNamedItemNS(adoptNode(node));
1303: }
1304: }
1305: }
1306:
1307: public DOMConfiguration getDomConfig()
1308: {
1309: if (config == null)
1310: {
1311: config = new DomDocumentConfiguration();
1312: }
1313: return config;
1314: }
1315:
1316: public void normalizeDocument()
1317: {
1318: boolean save = building;
1319: building = true;
1320: normalizeNode(this);
1321: building = save;
1322: }
1323:
1324: void normalizeNode(DomNode node)
1325: {
1326: node.normalize();
1327: if (config != null)
1328: {
1329: switch (node.nodeType)
1330: {
1331: case CDATA_SECTION_NODE:
1332: if (!config.cdataSections)
1333: {
1334:
1335: Text text = createTextNode(node.getNodeValue());
1336: node.parent.insertBefore(text, node);
1337: node.parent.removeChild(node);
1338:
1339: String data = text.getWholeText();
1340: node = (DomNode) text.replaceWholeText(data);
1341: }
1342: else if (config.splitCdataSections)
1343: {
1344: String value = node.getNodeValue();
1345: int i = value.indexOf("]]>");
1346: while (i != -1)
1347: {
1348: Node node2 = createCDATASection(value.substring(0, i));
1349: node.parent.insertBefore(node2, node);
1350: value = value.substring(i + 3);
1351: node.setNodeValue(value);
1352: i = value.indexOf("]]>");
1353: }
1354: }
1355: break;
1356: case COMMENT_NODE:
1357: if (!config.comments)
1358: {
1359: node.parent.removeChild(node);
1360: }
1361: break;
1362: case TEXT_NODE:
1363: if (!config.elementContentWhitespace &&
1364: ((Text) node).isElementContentWhitespace())
1365: {
1366: node.parent.removeChild(node);
1367: }
1368: break;
1369: case ENTITY_REFERENCE_NODE:
1370: if (!config.entities)
1371: {
1372: for (DomNode ctx = node.first; ctx != null; )
1373: {
1374: DomNode ctxNext = ctx.next;
1375: node.parent.insertBefore(ctx, node);
1376: ctx = ctxNext;
1377: }
1378: node.parent.removeChild(node);
1379: }
1380: break;
1381: case ELEMENT_NODE:
1382: if (!config.namespaceDeclarations)
1383: {
1384: DomNamedNodeMap attrs =
1385: (DomNamedNodeMap) node.getAttributes();
1386: boolean aro = attrs.readonly;
1387: attrs.readonly = false;
1388: int len = attrs.getLength();
1389: for (int i = 0; i < len; i++)
1390: {
1391: Node attr = attrs.item(i);
1392: String namespace = attr.getNamespaceURI();
1393: if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespace))
1394: {
1395: attrs.removeNamedItemNS(namespace,
1396: attr.getLocalName());
1397: i--;
1398: len--;
1399: }
1400: }
1401: attrs.readonly = aro;
1402: }
1403: break;
1404: }
1405: }
1406: for (DomNode ctx = node.first; ctx != null; )
1407: {
1408: DomNode ctxNext = ctx.next;
1409: normalizeNode(ctx);
1410: ctx = ctxNext;
1411: }
1412: }
1413:
1414: public Node renameNode(Node n, String namespaceURI, String qualifiedName)
1415: throws DOMException
1416: {
1417: if (n instanceof DomNsNode)
1418: {
1419: DomNsNode src = (DomNsNode) n;
1420: if (src == null)
1421: {
1422: throw new DomDOMException(DOMException.NOT_FOUND_ERR);
1423: }
1424: if (src.owner != this)
1425: {
1426: throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
1427: null, src, 0);
1428: }
1429: boolean xml11 = "1.1".equals(version);
1430: checkName(qualifiedName, xml11);
1431: int ci = qualifiedName.indexOf(':');
1432: if ("".equals(namespaceURI))
1433: {
1434: namespaceURI = null;
1435: }
1436: if (namespaceURI != null)
1437: {
1438: checkNCName(qualifiedName, xml11);
1439: String prefix = (ci == -1) ? "" :
1440: qualifiedName.substring(0, ci);
1441: if (XMLConstants.XML_NS_PREFIX.equals(prefix) &&
1442: !XMLConstants.XML_NS_URI.equals(namespaceURI))
1443: {
1444: throw new DomDOMException(DOMException.NAMESPACE_ERR,
1445: "xml namespace must be " +
1446: XMLConstants.XML_NS_URI, src, 0);
1447: }
1448: else if (src.nodeType == ATTRIBUTE_NODE &&
1449: (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
1450: XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName)) &&
1451: !XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
1452: {
1453: throw new DomDOMException(DOMException.NAMESPACE_ERR,
1454: "xmlns namespace must be " +
1455: XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0);
1456: }
1457: if (XMLConstants.XML_NS_URI.equals(namespaceURI) &&
1458: !XMLConstants.XML_NS_PREFIX.equals(prefix))
1459: {
1460: throw new DomDOMException(DOMException.NAMESPACE_ERR,
1461: "xml namespace must be " +
1462: XMLConstants.XML_NS_URI, src, 0);
1463: }
1464: else if (src.nodeType == ATTRIBUTE_NODE &&
1465: XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI) &&
1466: !(XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
1467: XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName)))
1468: {
1469: throw new DomDOMException(DOMException.NAMESPACE_ERR,
1470: "xmlns namespace must be " +
1471: XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0);
1472: }
1473:
1474: }
1475: src.setNodeName(qualifiedName);
1476: src.setNamespaceURI(namespaceURI);
1477: src.notifyUserDataHandlers(UserDataHandler.NODE_RENAMED, src, src);
1478:
1479:
1480: return src;
1481: }
1482: throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, n, 0);
1483: }
1484:
1485:
1486:
1487: public XPathExpression createExpression(String expression,
1488: XPathNSResolver resolver)
1489: throws XPathException, DOMException
1490: {
1491: return new DomXPathExpression(this, expression, resolver);
1492: }
1493:
1494: public XPathNSResolver createNSResolver(Node nodeResolver)
1495: {
1496: return new DomXPathNSResolver(nodeResolver);
1497: }
1498:
1499: public Object evaluate(String expression,
1500: Node contextNode,
1501: XPathNSResolver resolver,
1502: short type,
1503: Object result)
1504: throws XPathException, DOMException
1505: {
1506: XPathExpression xpe =
1507: new DomXPathExpression(this, expression, resolver);
1508: return xpe.evaluate(contextNode, type, result);
1509: }
1510:
1511: }