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