1 /* DomDocument.java -- 2 Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package gnu.xml.dom; 39 40 import java.util.Iterator; 41 import javax.xml.XMLConstants; 42 43 import org.w3c.dom.Attr; 44 import org.w3c.dom.CDATASection; 45 import org.w3c.dom.Comment; 46 import org.w3c.dom.Document; 47 import org.w3c.dom.DocumentFragment; 48 import org.w3c.dom.DocumentType; 49 import org.w3c.dom.DOMConfiguration; 50 import org.w3c.dom.DOMImplementation; 51 import org.w3c.dom.DOMException; 52 import org.w3c.dom.Element; 53 import org.w3c.dom.Entity; 54 import org.w3c.dom.EntityReference; 55 import org.w3c.dom.NamedNodeMap; 56 import org.w3c.dom.Node; 57 import org.w3c.dom.Notation; 58 import org.w3c.dom.ProcessingInstruction; 59 import org.w3c.dom.Text; 60 import org.w3c.dom.UserDataHandler; 61 import org.w3c.dom.traversal.DocumentTraversal; 62 import org.w3c.dom.traversal.NodeFilter; 63 import org.w3c.dom.traversal.NodeIterator; 64 import org.w3c.dom.traversal.TreeWalker; 65 import org.w3c.dom.xpath.XPathEvaluator; 66 import org.w3c.dom.xpath.XPathException; 67 import org.w3c.dom.xpath.XPathExpression; 68 import org.w3c.dom.xpath.XPathNSResolver; 69 70 /** 71 * <p> "Document" and "DocumentTraversal" implementation. 72 * 73 * <p> Note that when this checks names for legality, it uses an 74 * approximation of the XML rules, not the real ones. Specifically, 75 * it uses Unicode rules, with sufficient tweaks to pass a majority 76 * of basic XML conformance tests. (The huge XML character tables are 77 * hairy to implement.) 78 * 79 * @author David Brownell 80 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> 81 */ 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 private boolean defaultAttributes = true; 91 92 boolean building; // if true, skip mutation events in the tree 93 94 DomDocumentConfiguration config; 95 96 String inputEncoding; 97 String encoding; 98 String version = "1.0"; 99 boolean standalone; 100 String systemId; 101 102 /** 103 * Constructs a Document node, associating it with an instance 104 * of the DomImpl class. 105 * 106 * <p> Note that this constructor disables character checking. 107 * It is normally used when connecting a DOM to an XML parser, 108 * and duplicating such checks is undesirable. When used for 109 * purposes other than connecting to a parser, you should 110 * re-enable that checking. 111 * 112 * @see #setCheckingCharacters 113 */ DomDocument()114 public DomDocument() 115 { 116 this(new DomImpl()); 117 } 118 119 /** 120 * Constructs a Document node, associating it with the specified 121 * implementation. This should only be used in conjunction with 122 * a specialized implementation; it will normally be called by 123 * that implementation. 124 * 125 * @see DomImpl 126 * @see #setCheckingCharacters 127 */ DomDocument(DOMImplementation impl)128 protected DomDocument(DOMImplementation impl) 129 { 130 super(DOCUMENT_NODE, null); 131 implementation = impl; 132 } 133 134 /** 135 * Sets the <code>building</code> flag. 136 * Mutation events in the document are not reported. 137 */ setBuilding(boolean flag)138 public void setBuilding(boolean flag) 139 { 140 building = flag; 141 } 142 143 /** 144 * Sets whether to check for document well-formedness. 145 * If true, an exception will be raised if a second doctype or root 146 * element node is added to the document. 147 */ setCheckWellformedness(boolean flag)148 public void setCheckWellformedness(boolean flag) 149 { 150 checkingWellformedness = flag; 151 } 152 153 /** 154 * Sets whether to check for document characters. 155 */ setCheckingCharacters(boolean flag)156 public void setCheckingCharacters(boolean flag) 157 { 158 checkingCharacters = flag; 159 } 160 161 /** 162 * Sets whether to default attributes for new elements. 163 */ setDefaultAttributes(boolean flag)164 public void setDefaultAttributes(boolean flag) 165 { 166 defaultAttributes = flag; 167 } 168 169 /** 170 * <b>DOM L1</b> 171 * Returns the constant "#document". 172 */ getNodeName()173 final public String getNodeName() 174 { 175 return "#document"; 176 } 177 178 /** 179 * <b>DOM L1</b> 180 * Returns the document's root element, or null. 181 */ getDocumentElement()182 final public Element getDocumentElement() 183 { 184 for (DomNode ctx = first; ctx != null; ctx = ctx.next) 185 { 186 if (ctx.nodeType == ELEMENT_NODE) 187 { 188 return (Element) ctx; 189 } 190 } 191 return null; 192 } 193 194 /** 195 * <b>DOM L1</b> 196 * Returns the document's DocumentType, or null. 197 */ getDoctype()198 final public DocumentType getDoctype() 199 { 200 for (DomNode ctx = first; ctx != null; ctx = ctx.next) 201 { 202 if (ctx.nodeType == DOCUMENT_TYPE_NODE) 203 { 204 return (DocumentType) ctx; 205 } 206 } 207 return null; 208 } 209 210 /** 211 * <b>DOM L1</b> 212 * Returns the document's DOMImplementation. 213 */ getImplementation()214 final public DOMImplementation getImplementation() 215 { 216 return implementation; 217 } 218 219 /** 220 * <b>DOM L1 (relocated in DOM L2)</b> 221 * Returns the element with the specified "ID" attribute, or null. 222 * 223 * <p>Returns null unless {@link Consumer} was used to populate internal 224 * DTD declaration information, using package-private APIs. If that 225 * internal DTD information is available, the document may be searched for 226 * the element with that ID. 227 */ getElementById(String id)228 public Element getElementById(String id) 229 { 230 if (id == null || id.length() == 0) 231 { 232 return null; 233 } 234 DomDoctype doctype = (DomDoctype) getDoctype(); 235 if (doctype != null && !doctype.hasIds()) 236 { 237 doctype = null; 238 } 239 240 // yes, this is linear in size of document. 241 // it'd be easy enough to maintain a hashtable. 242 Node current = getDocumentElement(); 243 Node temp; 244 245 if (current == null) 246 { 247 return null; 248 } 249 while (current != this) 250 { 251 // done? 252 if (current.getNodeType() == ELEMENT_NODE) 253 { 254 DomElement element = (DomElement) current; 255 if (element.userIdAttrs != null) 256 { 257 for (Iterator i = element.userIdAttrs.iterator(); 258 i.hasNext(); ) 259 { 260 Node idAttr = (Node) i.next(); 261 if (id.equals(idAttr.getNodeValue())) 262 { 263 return element; 264 } 265 } 266 } 267 if (doctype != null) 268 { 269 DTDElementTypeInfo info = 270 doctype.getElementTypeInfo(current.getNodeName()); 271 if (info != null && 272 id.equals(element.getAttribute(info.idAttrName))) 273 { 274 return element; 275 } 276 } 277 // xml:id 278 String xmlId = element.getAttribute("xml:id"); 279 if (xmlId == null) 280 { 281 xmlId = element.getAttributeNS(XMLConstants.XML_NS_URI, 282 "id"); 283 } 284 if (id.equals(xmlId)) 285 { 286 return element; 287 } 288 } 289 290 // descend? 291 if (current.hasChildNodes()) 292 { 293 current = current.getFirstChild(); 294 continue; 295 } 296 297 // lateral? 298 temp = current.getNextSibling(); 299 if (temp != null) 300 { 301 current = temp; 302 continue; 303 } 304 305 // back up ... 306 do 307 { 308 temp = current.getParentNode(); 309 if (temp == null) 310 { 311 return null; 312 } 313 current = temp; 314 temp = current.getNextSibling(); 315 } 316 while (temp == null); 317 current = temp; 318 } 319 return null; 320 } 321 checkNewChild(Node newChild)322 private void checkNewChild(Node newChild) 323 { 324 if (newChild.getNodeType() == ELEMENT_NODE 325 && getDocumentElement() != null) 326 { 327 throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR, 328 "document element already present: " + 329 getDocumentElement(), newChild, 0); 330 } 331 if (newChild.getNodeType() == DOCUMENT_TYPE_NODE 332 && getDoctype() != null) 333 { 334 throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR, 335 "document type already present: " + 336 getDoctype(), newChild, 0); 337 } 338 } 339 340 /** 341 * <b>DOM L1</b> 342 * Appends the specified node to this node's list of children, 343 * enforcing the constraints that there be only one root element 344 * and one document type child. 345 */ appendChild(Node newChild)346 public Node appendChild(Node newChild) 347 { 348 if (checkingWellformedness) 349 { 350 checkNewChild(newChild); 351 } 352 return super.appendChild(newChild); 353 } 354 355 /** 356 * <b>DOM L1</b> 357 * Inserts the specified node in this node's list of children, 358 * enforcing the constraints that there be only one root element 359 * and one document type child. 360 */ insertBefore(Node newChild, Node refChild)361 public Node insertBefore(Node newChild, Node refChild) 362 { 363 if (checkingWellformedness) 364 { 365 checkNewChild(newChild); 366 } 367 return super.insertBefore(newChild, refChild); 368 } 369 370 /** 371 * <b>DOM L1</b> 372 * Replaces the specified node in this node's list of children, 373 * enforcing the constraints that there be only one root element 374 * and one document type child. 375 */ replaceChild(Node newChild, Node refChild)376 public Node replaceChild(Node newChild, Node refChild) 377 { 378 if (checkingWellformedness && 379 ((newChild.getNodeType() == ELEMENT_NODE && 380 refChild.getNodeType() != ELEMENT_NODE) || 381 (newChild.getNodeType() == DOCUMENT_TYPE_NODE && 382 refChild.getNodeType() != DOCUMENT_TYPE_NODE))) 383 { 384 checkNewChild(newChild); 385 } 386 return super.replaceChild(newChild, refChild); 387 } 388 389 // NOTE: DOM can't really tell when the name of an entity, 390 // notation, or PI must follow the namespace rules (excluding 391 // colons) instead of the XML rules (which allow them without 392 // much restriction). That's an API issue. verifyXmlName 393 // aims to enforce the XML rules, not the namespace rules. 394 395 /** 396 * Throws a DOM exception if the specified name is not a legal XML 1.0 397 * Name. 398 * @deprecated This method is deprecated and may be removed in future 399 * versions of GNU JAXP 400 */ verifyXmlName(String name)401 public static void verifyXmlName(String name) 402 { 403 // XXX why is this public? 404 checkName(name, false); 405 } 406 checkName(String name, boolean xml11)407 static void checkName(String name, boolean xml11) 408 { 409 if (name == null) 410 { 411 throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0); 412 } 413 int len = name.length(); 414 if (len == 0) 415 { 416 throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0); 417 } 418 419 // dog: rewritten to use the rules for XML 1.0 and 1.1 420 421 // Name start character 422 char c = name.charAt(0); 423 if (xml11) 424 { 425 // XML 1.1 426 if ((c < 0x0041 || c > 0x005a) && 427 (c < 0x0061 || c > 0x007a) && 428 c != ':' && c != '_' && 429 (c < 0x00c0 || c > 0x00d6) && 430 (c < 0x00d8 || c > 0x00f6) && 431 (c < 0x00f8 || c > 0x02ff) && 432 (c < 0x0370 || c > 0x037d) && 433 (c < 0x037f || c > 0x1fff) && 434 (c < 0x200c || c > 0x200d) && 435 (c < 0x2070 || c > 0x218f) && 436 (c < 0x2c00 || c > 0x2fef) && 437 (c < 0x3001 || c > 0xd7ff) && 438 (c < 0xf900 || c > 0xfdcf) && 439 (c < 0xfdf0 || c > 0xfffd) && 440 (c < 0x10000 || c > 0xeffff)) 441 { 442 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, 443 name, null, c); 444 } 445 } 446 else 447 { 448 // XML 1.0 449 int type = Character.getType(c); 450 switch (type) 451 { 452 case Character.LOWERCASE_LETTER: // Ll 453 case Character.UPPERCASE_LETTER: // Lu 454 case Character.OTHER_LETTER: // Lo 455 case Character.TITLECASE_LETTER: // Lt 456 case Character.LETTER_NUMBER: // Nl 457 if ((c > 0xf900 && c < 0xfffe) || 458 (c >= 0x20dd && c <= 0x20e0)) 459 { 460 // Compatibility area and Unicode 2.0 exclusions 461 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, 462 name, null, c); 463 } 464 break; 465 default: 466 if (c != ':' && c != '_' && (c < 0x02bb || c > 0x02c1) && 467 c != 0x0559 && c != 0x06e5 && c != 0x06e6) 468 { 469 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, 470 name, null, c); 471 } 472 } 473 } 474 475 // Subsequent characters 476 for (int i = 1; i < len; i++) 477 { 478 c = name.charAt(i); 479 if (xml11) 480 { 481 // XML 1.1 482 if ((c < 0x0041 || c > 0x005a) && 483 (c < 0x0061 || c > 0x007a) && 484 (c < 0x0030 || c > 0x0039) && 485 c != ':' && c != '_' && c != '-' && c != '.' && 486 (c < 0x00c0 || c > 0x00d6) && 487 (c < 0x00d8 || c > 0x00f6) && 488 (c < 0x00f8 || c > 0x02ff) && 489 (c < 0x0370 || c > 0x037d) && 490 (c < 0x037f || c > 0x1fff) && 491 (c < 0x200c || c > 0x200d) && 492 (c < 0x2070 || c > 0x218f) && 493 (c < 0x2c00 || c > 0x2fef) && 494 (c < 0x3001 || c > 0xd7ff) && 495 (c < 0xf900 || c > 0xfdcf) && 496 (c < 0xfdf0 || c > 0xfffd) && 497 (c < 0x10000 || c > 0xeffff) && 498 c != 0x00b7 && 499 (c < 0x0300 || c > 0x036f) && 500 (c < 0x203f || c > 0x2040)) 501 { 502 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, name, 503 null, c); 504 } 505 } 506 else 507 { 508 // XML 1.0 509 int type = Character.getType(c); 510 switch (type) 511 { 512 case Character.LOWERCASE_LETTER: // Ll 513 case Character.UPPERCASE_LETTER: // Lu 514 case Character.DECIMAL_DIGIT_NUMBER: // Nd 515 case Character.OTHER_LETTER: // Lo 516 case Character.TITLECASE_LETTER: // Lt 517 case Character.LETTER_NUMBER: // Nl 518 case Character.COMBINING_SPACING_MARK: // Mc 519 case Character.ENCLOSING_MARK: // Me 520 case Character.NON_SPACING_MARK: // Mn 521 case Character.MODIFIER_LETTER: // Lm 522 if ((c > 0xf900 && c < 0xfffe) || 523 (c >= 0x20dd && c <= 0x20e0)) 524 { 525 // Compatibility area and Unicode 2.0 exclusions 526 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, 527 name, null, c); 528 } 529 break; 530 default: 531 if (c != '-' && c != '.' && c != ':' && c != '_' && 532 c != 0x0387 && (c < 0x02bb || c > 0x02c1) && 533 c != 0x0559 && c != 0x06e5 && c != 0x06e6 && c != 0x00b7) 534 { 535 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, 536 name, null, c); 537 } 538 } 539 } 540 } 541 542 // FIXME characters with a font or compatibility decomposition (i.e. 543 // those with a "compatibility formatting tag" in field 5 of the 544 // database -- marked by field 5 beginning with a "<") are not allowed. 545 } 546 547 // package private checkNCName(String name, boolean xml11)548 static void checkNCName(String name, boolean xml11) 549 { 550 checkName(name, xml11); 551 int len = name.length(); 552 int index = name.indexOf(':'); 553 if (index != -1) 554 { 555 if (index == 0 || index == (len - 1) || name.lastIndexOf(':') != index) 556 { 557 throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0); 558 } 559 } 560 } 561 562 // package private checkChar(String value, boolean xml11)563 static void checkChar(String value, boolean xml11) 564 { 565 char[] chars = value.toCharArray(); 566 checkChar(chars, 0, chars.length, xml11); 567 } 568 checkChar(char[] buf, int off, int len, boolean xml11)569 static void checkChar(char[] buf, int off, int len, boolean xml11) 570 { 571 for (int i = 0; i < len; i++) 572 { 573 char c = buf[i]; 574 575 // assume surrogate pairing checks out OK, for simplicity 576 if ((c >= 0x0020 && c <= 0xd7ff) || 577 (c == 0x000a || c == 0x000d || c == 0x0009) || 578 (c >= 0xe000 && c <= 0xfffd) || 579 (c >= 0x10000 && c <= 0x10ffff)) 580 { 581 continue; 582 } 583 if (xml11) 584 { 585 if ((c >= 0x0001 && c <= 0x001f) || 586 (c >= 0x007f && c <= 0x0084) || 587 (c >= 0x0086 && c <= 0x009f)) 588 { 589 continue; 590 } 591 } 592 throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, 593 new String(buf, off, len), null, c); 594 } 595 } 596 597 /** 598 * <b>DOM L1</b> 599 * Returns a newly created element with the specified name. 600 * The node name of the created element will be equal to {@code name}. 601 * The namespace, prefix and local name will all be {@code null}. 602 */ createElement(String name)603 public Element createElement(String name) 604 { 605 Element element; 606 607 if (checkingCharacters) 608 { 609 checkName(name, "1.1".equals(version)); 610 } 611 if (name.startsWith("xml:")) 612 { 613 element = createElementNS(null, name); 614 } 615 else 616 { 617 DomElement domElement = new DomElement(this, null, name, null, null); 618 element = domElement; 619 } 620 if (defaultAttributes) 621 setDefaultAttributes(element, name); 622 return element; 623 } 624 625 /** 626 * <b>DOM L2</b> 627 * Returns a newly created element with the specified name 628 * and namespace information. 629 */ createElementNS(String namespaceURI, String name)630 public Element createElementNS(String namespaceURI, String name) 631 { 632 if (checkingCharacters) 633 { 634 checkNCName(name, "1.1".equals(version)); 635 } 636 637 if ("".equals(namespaceURI)) 638 { 639 namespaceURI = null; 640 } 641 if (name.startsWith("xml:")) 642 { 643 if (namespaceURI != null 644 && !XMLConstants.XML_NS_URI.equals(namespaceURI)) 645 { 646 throw new DomDOMException(DOMException.NAMESPACE_ERR, 647 "xml namespace is always " + 648 XMLConstants.XML_NS_URI, this, 0); 649 } 650 namespaceURI = XMLConstants.XML_NS_URI; 651 } 652 else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) || 653 name.startsWith("xmlns:")) 654 { 655 throw new DomDOMException(DOMException.NAMESPACE_ERR, 656 "xmlns is reserved", this, 0); 657 } 658 else if (namespaceURI == null && name.indexOf(':') != -1) 659 { 660 throw new DomDOMException(DOMException.NAMESPACE_ERR, 661 "prefixed name '" + name + 662 "' needs a URI", this, 0); 663 } 664 665 Element element = new DomElement(this, namespaceURI, name); 666 if (defaultAttributes) 667 setDefaultAttributes(element, name); 668 return element; 669 } 670 setDefaultAttributes(Element element, String name)671 private void setDefaultAttributes(Element element, String name) 672 { 673 DomDoctype doctype = (DomDoctype) getDoctype(); 674 if (doctype == null) 675 { 676 return; 677 } 678 679 // default any attributes that need it 680 DTDElementTypeInfo info = doctype.getElementTypeInfo(name); 681 if (info != null) 682 { 683 for (Iterator i = info.attributes(); i != null && i.hasNext(); ) 684 { 685 DTDAttributeTypeInfo attr = (DTDAttributeTypeInfo) i.next(); 686 String value = attr.value; 687 if ("#IMPLIED".equals(attr.mode) && value == null) 688 continue; 689 DomAttr node = (DomAttr) createAttribute(attr.name); 690 691 if (value == null) 692 { 693 value = ""; 694 } 695 node.setValue(value); 696 node.setSpecified(false); 697 element.setAttributeNode(node); 698 } 699 } 700 } 701 702 /** 703 * <b>DOM L1</b> 704 * Returns a newly created document fragment. 705 */ createDocumentFragment()706 public DocumentFragment createDocumentFragment() 707 { 708 return new DomDocumentFragment(this); 709 } 710 711 /** 712 * <b>DOM L1</b> 713 * Returns a newly created text node with the specified value. 714 */ createTextNode(String value)715 public Text createTextNode(String value) 716 { 717 if (checkingCharacters) 718 { 719 checkChar(value, "1.1".equals(version)); 720 } 721 return new DomText(this, value); 722 } 723 724 /** 725 * Returns a newly created text node with the specified value. 726 */ createTextNode(char[] buf, int off, int len)727 public Text createTextNode(char[] buf, int off, int len) 728 { 729 if (checkingCharacters) 730 { 731 checkChar(buf, off, len, "1.1".equals(version)); 732 } 733 return new DomText(this, buf, off, len); 734 } 735 736 /** 737 * <b>DOM L1</b> 738 * Returns a newly created comment node with the specified value. 739 */ createComment(String value)740 public Comment createComment(String value) 741 { 742 if (checkingCharacters) 743 { 744 checkChar(value, "1.1".equals(version)); 745 } 746 return new DomComment(this, value); 747 } 748 749 /** 750 * <b>DOM L1</b> 751 * Returns a newly created CDATA section node with the specified value. 752 */ createCDATASection(String value)753 public CDATASection createCDATASection(String value) 754 { 755 if (checkingCharacters) 756 { 757 checkChar(value, "1.1".equals(version)); 758 } 759 return new DomCDATASection(this, value); 760 } 761 762 /** 763 * Returns a newly created CDATA section node with the specified value. 764 */ createCDATASection(char[] buf, int off, int len)765 public CDATASection createCDATASection(char[] buf, int off, int len) 766 { 767 if (checkingCharacters) 768 { 769 checkChar(buf, off, len, "1.1".equals(version)); 770 } 771 return new DomCDATASection(this, buf, off, len); 772 } 773 774 /** 775 * <b>DOM L1</b> 776 * Returns a newly created processing instruction. 777 */ createProcessingInstruction(String target, String data)778 public ProcessingInstruction createProcessingInstruction(String target, 779 String data) 780 { 781 if (checkingCharacters) 782 { 783 boolean xml11 = "1.1".equals(version); 784 checkName(target, xml11); 785 if ("xml".equalsIgnoreCase(target)) 786 { 787 throw new DomDOMException(DOMException.SYNTAX_ERR, 788 "illegal PI target name", 789 this, 0); 790 } 791 checkChar(data, xml11); 792 } 793 return new DomProcessingInstruction(this, target, data); 794 } 795 796 /** 797 * <b>DOM L1</b> 798 * Returns a newly created attribute with the specified name. 799 */ createAttribute(String name)800 public Attr createAttribute(String name) 801 { 802 if (checkingCharacters) 803 { 804 checkName(name, "1.1".equals(version)); 805 } 806 if (name.startsWith("xml:")) 807 { 808 return createAttributeNS(XMLConstants.XML_NS_URI, name); 809 } 810 else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) || 811 name.startsWith("xmlns:")) 812 { 813 return createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, name); 814 } 815 else 816 { 817 DomAttr ret = new DomAttr(this, null, name, null, null); 818 return ret; 819 } 820 } 821 822 /** 823 * <b>DOM L2</b> 824 * Returns a newly created attribute with the specified name 825 * and namespace information. 826 */ createAttributeNS(String namespaceURI, String name)827 public Attr createAttributeNS(String namespaceURI, String name) 828 { 829 if (checkingCharacters) 830 { 831 checkNCName(name, "1.1".equals(version)); 832 } 833 834 if ("".equals(namespaceURI)) 835 { 836 namespaceURI = null; 837 } 838 if (name.startsWith ("xml:")) 839 { 840 if (namespaceURI == null) 841 { 842 namespaceURI = XMLConstants.XML_NS_URI; 843 } 844 else if (!XMLConstants.XML_NS_URI.equals(namespaceURI)) 845 { 846 throw new DomDOMException(DOMException.NAMESPACE_ERR, 847 "xml namespace is always " + 848 XMLConstants.XML_NS_URI, 849 this, 0); 850 } 851 } 852 else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) || 853 name.startsWith("xmlns:")) 854 { 855 if (namespaceURI == null) 856 { 857 namespaceURI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; 858 } 859 else if (!XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) 860 { 861 throw new DomDOMException(DOMException.NAMESPACE_ERR, 862 "xmlns namespace must be " + 863 XMLConstants.XMLNS_ATTRIBUTE_NS_URI, 864 this, 0); 865 } 866 } 867 else if (namespaceURI == null && name.indexOf(':') != -1) 868 { 869 throw new DomDOMException(DOMException.NAMESPACE_ERR, 870 "prefixed name needs a URI: " + name, this, 0); 871 } 872 return new DomAttr(this, namespaceURI, name); 873 } 874 875 /** 876 * <b>DOM L1</b> 877 * Returns a newly created reference to the specified entity. 878 * The caller should populate this with the appropriate children 879 * and then mark it as readonly. 880 * 881 * @see DomNode#makeReadonly 882 */ createEntityReference(String name)883 public EntityReference createEntityReference(String name) 884 { 885 DomEntityReference ret = new DomEntityReference(this, name); 886 DocumentType doctype = getDoctype(); 887 if (doctype != null) 888 { 889 DomEntity ent = (DomEntity) doctype.getEntities().getNamedItem(name); 890 if (ent != null) 891 { 892 for (DomNode ctx = ent.first; ctx != null; ctx = ctx.next) 893 { 894 ret.appendChild(ctx.cloneNode(true)); 895 } 896 } 897 } 898 ret.makeReadonly(); 899 return ret; 900 } 901 902 /** 903 * <b>DOM L2</b> 904 * Makes a copy of the specified node, with all nodes "owned" by 905 * this document and with children optionally copied. This type 906 * of standard utility has become, well, a standard utility. 907 * 908 * <p> Note that EntityReference nodes created through this method (either 909 * directly, or recursively) never have children, and that there is no 910 * portable way to associate them with such children. 911 * 912 * <p> Note also that there is no requirement that the specified node 913 * be associated with a different document. This differs from the 914 * <em>cloneNode</em> operation in that the node itself is not given 915 * an opportunity to participate, so that any information managed 916 * by node subclasses will be lost. 917 */ importNode(Node src, boolean deep)918 public Node importNode(Node src, boolean deep) 919 { 920 Node dst = null; 921 switch (src.getNodeType()) 922 { 923 case TEXT_NODE: 924 dst = createTextNode(src.getNodeValue()); 925 break; 926 case CDATA_SECTION_NODE: 927 dst = createCDATASection(src.getNodeValue()); 928 break; 929 case COMMENT_NODE: 930 dst = createComment(src.getNodeValue()); 931 break; 932 case PROCESSING_INSTRUCTION_NODE: 933 dst = createProcessingInstruction(src.getNodeName(), 934 src.getNodeValue()); 935 break; 936 case NOTATION_NODE: 937 // NOTE: There's no standard way to create 938 // these, or add them to a doctype. Useless. 939 Notation notation = (Notation) src; 940 dst = new DomNotation(this, notation.getNodeName(), 941 notation.getPublicId(), 942 notation.getSystemId()); 943 break; 944 case ENTITY_NODE: 945 // NOTE: There's no standard way to create 946 // these, or add them to a doctype. Useless. 947 Entity entity = (Entity) src; 948 dst = new DomEntity(this, entity.getNodeName(), 949 entity.getPublicId(), 950 entity.getSystemId(), 951 entity.getNotationName()); 952 if (deep) 953 { 954 for (Node ctx = src.getFirstChild(); ctx != null; 955 ctx = ctx.getNextSibling()) 956 { 957 dst.appendChild(importNode(ctx, deep)); 958 } 959 } 960 break; 961 case ENTITY_REFERENCE_NODE: 962 dst = createEntityReference(src.getNodeName()); 963 break; 964 case DOCUMENT_FRAGMENT_NODE: 965 dst = new DomDocumentFragment(this); 966 if (deep) 967 { 968 for (Node ctx = src.getFirstChild(); ctx != null; 969 ctx = ctx.getNextSibling()) 970 { 971 dst.appendChild(importNode(ctx, deep)); 972 } 973 } 974 break; 975 case ATTRIBUTE_NODE: 976 String attr_nsuri = src.getNamespaceURI(); 977 if (attr_nsuri != null) 978 { 979 dst = createAttributeNS(attr_nsuri, src.getNodeName()); 980 } 981 else 982 { 983 dst = createAttribute(src.getNodeName()); 984 } 985 // this is _always_ done regardless of "deep" setting 986 for (Node ctx = src.getFirstChild(); ctx != null; 987 ctx = ctx.getNextSibling()) 988 { 989 dst.appendChild(importNode(ctx, false)); 990 } 991 break; 992 case ELEMENT_NODE: 993 String elem_nsuri = src.getNamespaceURI(); 994 if (elem_nsuri != null) 995 { 996 dst = createElementNS(elem_nsuri, src.getNodeName()); 997 } 998 else 999 { 1000 dst = createElement(src.getNodeName()); 1001 } 1002 NamedNodeMap srcAttrs = src.getAttributes(); 1003 NamedNodeMap dstAttrs = dst.getAttributes(); 1004 int len = srcAttrs.getLength(); 1005 for (int i = 0; i < len; i++) 1006 { 1007 Attr a = (Attr) srcAttrs.item(i); 1008 Attr dflt; 1009 1010 // maybe update defaulted attributes 1011 dflt = (Attr) dstAttrs.getNamedItem(a.getNodeName()); 1012 if (dflt != null) 1013 { 1014 String newval = a.getNodeValue(); 1015 if (!dflt.getNodeValue().equals(newval) 1016 || a.getSpecified () == true) 1017 { 1018 dflt.setNodeValue (newval); 1019 } 1020 continue; 1021 } 1022 1023 dstAttrs.setNamedItem((Attr) importNode(a, false)); 1024 } 1025 if (deep) 1026 { 1027 for (Node ctx = src.getFirstChild(); ctx != null; 1028 ctx = ctx.getNextSibling()) 1029 { 1030 dst.appendChild(importNode(ctx, true)); 1031 } 1032 } 1033 break; 1034 // can't import document or doctype nodes 1035 case DOCUMENT_NODE: 1036 case DOCUMENT_TYPE_NODE: 1037 // FALLTHROUGH 1038 // can't import unrecognized or nonstandard nodes 1039 default: 1040 throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, src, 0); 1041 } 1042 1043 // FIXME cleanup a bit -- for deep copies, copy those 1044 // children in one place, here (code sharing is healthy) 1045 1046 if (src instanceof DomNode) 1047 { 1048 ((DomNode) src).notifyUserDataHandlers(UserDataHandler.NODE_IMPORTED, 1049 src, dst); 1050 } 1051 return dst; 1052 } 1053 1054 /** 1055 * <b>DOM L2 (Traversal)</b> 1056 * Returns a newly created node iterator. Don't forget to detach 1057 * this iterator when you're done using it! 1058 * 1059 * @see DomIterator 1060 */ createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean expandEntities)1061 public NodeIterator createNodeIterator(Node root, 1062 int whatToShow, 1063 NodeFilter filter, 1064 boolean expandEntities) 1065 { 1066 return new DomNodeIterator(root, whatToShow, filter, expandEntities, 1067 false); 1068 } 1069 createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean expandEntities)1070 public TreeWalker createTreeWalker(Node root, 1071 int whatToShow, 1072 NodeFilter filter, 1073 boolean expandEntities) 1074 { 1075 return new DomNodeIterator(root, whatToShow, filter, expandEntities, 1076 true); 1077 } 1078 1079 // DOM Level 3 methods 1080 1081 /** 1082 * DOM L3 1083 */ getInputEncoding()1084 public String getInputEncoding() 1085 { 1086 return inputEncoding; 1087 } 1088 setInputEncoding(String inputEncoding)1089 public void setInputEncoding(String inputEncoding) 1090 { 1091 this.inputEncoding = inputEncoding; 1092 } 1093 1094 /** 1095 * DOM L3 1096 */ getXmlEncoding()1097 public String getXmlEncoding() 1098 { 1099 return encoding; 1100 } 1101 setXmlEncoding(String encoding)1102 public void setXmlEncoding(String encoding) 1103 { 1104 this.encoding = encoding; 1105 } 1106 getXmlStandalone()1107 public boolean getXmlStandalone() 1108 { 1109 return standalone; 1110 } 1111 setXmlStandalone(boolean xmlStandalone)1112 public void setXmlStandalone(boolean xmlStandalone) 1113 { 1114 standalone = xmlStandalone; 1115 } 1116 getXmlVersion()1117 public String getXmlVersion() 1118 { 1119 return version; 1120 } 1121 setXmlVersion(String xmlVersion)1122 public void setXmlVersion(String xmlVersion) 1123 { 1124 if (xmlVersion == null) 1125 { 1126 xmlVersion = "1.0"; 1127 } 1128 if ("1.0".equals(xmlVersion) || 1129 "1.1".equals(xmlVersion)) 1130 { 1131 version = xmlVersion; 1132 } 1133 else 1134 { 1135 throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR); 1136 } 1137 } 1138 getStrictErrorChecking()1139 public boolean getStrictErrorChecking() 1140 { 1141 return checkingCharacters; 1142 } 1143 setStrictErrorChecking(boolean strictErrorChecking)1144 public void setStrictErrorChecking(boolean strictErrorChecking) 1145 { 1146 checkingCharacters = strictErrorChecking; 1147 } 1148 lookupPrefix(String namespaceURI)1149 public String lookupPrefix(String namespaceURI) 1150 { 1151 Node root = getDocumentElement(); 1152 return (root == null) ? null : root.lookupPrefix(namespaceURI); 1153 } 1154 isDefaultNamespace(String namespaceURI)1155 public boolean isDefaultNamespace(String namespaceURI) 1156 { 1157 Node root = getDocumentElement(); 1158 return (root == null) ? false : root.isDefaultNamespace(namespaceURI); 1159 } 1160 lookupNamespaceURI(String prefix)1161 public String lookupNamespaceURI(String prefix) 1162 { 1163 Node root = getDocumentElement(); 1164 return (root == null) ? null : root.lookupNamespaceURI(prefix); 1165 } 1166 getBaseURI()1167 public String getBaseURI() 1168 { 1169 return getDocumentURI(); 1170 /* 1171 Node root = getDocumentElement(); 1172 if (root != null) 1173 { 1174 NamedNodeMap attrs = root.getAttributes(); 1175 Node xmlBase = attrs.getNamedItemNS(XMLConstants.XML_NS_URI, "base"); 1176 if (xmlBase != null) 1177 { 1178 return xmlBase.getNodeValue(); 1179 } 1180 } 1181 return systemId; 1182 */ 1183 } 1184 getDocumentURI()1185 public String getDocumentURI() 1186 { 1187 return systemId; 1188 } 1189 setDocumentURI(String documentURI)1190 public void setDocumentURI(String documentURI) 1191 { 1192 systemId = documentURI; 1193 } 1194 adoptNode(Node source)1195 public Node adoptNode(Node source) 1196 { 1197 int sourceNodeType = source.getNodeType(); 1198 switch (sourceNodeType) 1199 { 1200 case DOCUMENT_NODE: 1201 case DOCUMENT_TYPE_NODE: 1202 throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR); 1203 case ENTITY_NODE: 1204 case NOTATION_NODE: 1205 throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR); 1206 } 1207 if (source instanceof DomNode) 1208 { 1209 // GNU native 1210 DomNode src = (DomNode) source; 1211 DomNode dst = src; 1212 if (dst.parent != null) 1213 { 1214 dst = (DomNode) dst.cloneNode(true); 1215 } 1216 dst.setOwner(this); 1217 src.notifyUserDataHandlers(UserDataHandler.NODE_ADOPTED, src, dst); 1218 return dst; 1219 } 1220 else 1221 { 1222 // Some other implementation 1223 Node dst = null; 1224 switch (sourceNodeType) 1225 { 1226 case Node.ATTRIBUTE_NODE: 1227 { 1228 Attr src = (Attr) source; 1229 String nodeName = src.getNodeName(); 1230 String localName = src.getLocalName(); 1231 String namespaceUri = src.getNamespaceURI(); 1232 dst = (localName == null) ? 1233 createAttribute(nodeName) : 1234 createAttributeNS(namespaceUri, nodeName); 1235 adoptChildren(src, dst); 1236 break; 1237 } 1238 case Node.CDATA_SECTION_NODE: 1239 { 1240 CDATASection src = (CDATASection) source; 1241 dst = createCDATASection(src.getData()); 1242 break; 1243 } 1244 case Node.COMMENT_NODE: 1245 { 1246 Comment src = (Comment) source; 1247 dst = createComment(src.getData()); 1248 break; 1249 } 1250 case Node.DOCUMENT_FRAGMENT_NODE: 1251 { 1252 DocumentFragment src = (DocumentFragment) source; 1253 dst = createDocumentFragment(); 1254 adoptChildren(src, dst); 1255 break; 1256 } 1257 case Node.ELEMENT_NODE: 1258 { 1259 Element src = (Element) source; 1260 String nodeName = src.getNodeName(); 1261 String localName = src.getLocalName(); 1262 String namespaceUri = src.getNamespaceURI(); 1263 dst = (localName == null) ? 1264 createElement(nodeName) : 1265 createElementNS(namespaceUri, nodeName); 1266 adoptAttributes(src, dst); 1267 adoptChildren(src, dst); 1268 break; 1269 } 1270 case Node.ENTITY_REFERENCE_NODE: 1271 { 1272 EntityReference src = (EntityReference) source; 1273 dst = createEntityReference(src.getNodeName()); 1274 adoptChildren(src, dst); 1275 break; 1276 } 1277 case Node.PROCESSING_INSTRUCTION_NODE: 1278 { 1279 ProcessingInstruction src = (ProcessingInstruction) source; 1280 dst = createProcessingInstruction(src.getTarget(), 1281 src.getData()); 1282 break; 1283 } 1284 case Node.TEXT_NODE: 1285 { 1286 Text src = (Text) source; 1287 dst = createTextNode(src.getData()); 1288 break; 1289 } 1290 } 1291 return dst; 1292 } 1293 } 1294 adoptChildren(Node src, Node dst)1295 void adoptChildren(Node src, Node dst) 1296 { 1297 Node node = src.getFirstChild(); 1298 while (node != null) 1299 { 1300 Node next = node.getNextSibling(); 1301 dst.appendChild(adoptNode(node)); 1302 node = next; 1303 } 1304 } 1305 adoptAttributes(Node src, Node dst)1306 void adoptAttributes(Node src, Node dst) 1307 { 1308 NamedNodeMap srcAttrs = src.getAttributes(); 1309 NamedNodeMap dstAttrs = dst.getAttributes(); 1310 int len = srcAttrs.getLength(); 1311 for (int i = 0; i < len; i++) 1312 { 1313 Node node = srcAttrs.item(i); 1314 String localName = node.getLocalName(); 1315 if (localName == null) 1316 { 1317 dstAttrs.setNamedItem(adoptNode(node)); 1318 } 1319 else 1320 { 1321 dstAttrs.setNamedItemNS(adoptNode(node)); 1322 } 1323 } 1324 } 1325 getDomConfig()1326 public DOMConfiguration getDomConfig() 1327 { 1328 if (config == null) 1329 { 1330 config = new DomDocumentConfiguration(); 1331 } 1332 return config; 1333 } 1334 isEqualNode(Node arg)1335 public boolean isEqualNode(Node arg) 1336 { 1337 if (!super.isEqualNode(arg)) 1338 return false; 1339 Document d = (Document) arg; 1340 String dversion = d.getXmlVersion(); 1341 if (dversion == null || !dversion.equals(version)) 1342 return false; 1343 boolean dstandalone = d.getXmlStandalone(); 1344 if (dstandalone != standalone) 1345 return false; 1346 String dencoding = d.getXmlEncoding(); 1347 if (dencoding == null || dencoding.equalsIgnoreCase("UTF-8")) 1348 { 1349 if (encoding != null && !encoding.equalsIgnoreCase("UTF-8")) 1350 return false; 1351 } 1352 else 1353 { 1354 if (!dencoding.equals(encoding)) 1355 return false; 1356 } 1357 return true; 1358 } 1359 normalizeDocument()1360 public void normalizeDocument() 1361 { 1362 boolean save = building; 1363 building = true; 1364 normalizeNode(this); 1365 building = save; 1366 } 1367 normalizeNode(DomNode node)1368 void normalizeNode(DomNode node) 1369 { 1370 node.normalize(); 1371 if (config != null) 1372 { 1373 switch (node.nodeType) 1374 { 1375 case CDATA_SECTION_NODE: 1376 if (!config.cdataSections) 1377 { 1378 // replace CDATA section with text node 1379 Text text = createTextNode(node.getNodeValue()); 1380 node.parent.insertBefore(text, node); 1381 node.parent.removeChild(node); 1382 // merge adjacent text nodes 1383 String data = text.getWholeText(); 1384 node = (DomNode) text.replaceWholeText(data); 1385 } 1386 else if (config.splitCdataSections) 1387 { 1388 String value = node.getNodeValue(); 1389 int i = value.indexOf("]]>"); 1390 while (i != -1) 1391 { 1392 Node node2 = createCDATASection(value.substring(0, i)); 1393 node.parent.insertBefore(node2, node); 1394 value = value.substring(i + 3); 1395 node.setNodeValue(value); 1396 i = value.indexOf("]]>"); 1397 } 1398 } 1399 break; 1400 case COMMENT_NODE: 1401 if (!config.comments) 1402 { 1403 node.parent.removeChild(node); 1404 } 1405 break; 1406 case TEXT_NODE: 1407 if (!config.elementContentWhitespace && 1408 ((Text) node).isElementContentWhitespace()) 1409 { 1410 node.parent.removeChild(node); 1411 } 1412 break; 1413 case ENTITY_REFERENCE_NODE: 1414 if (!config.entities) 1415 { 1416 for (DomNode ctx = node.first; ctx != null; ) 1417 { 1418 DomNode ctxNext = ctx.next; 1419 node.parent.insertBefore(ctx, node); 1420 ctx = ctxNext; 1421 } 1422 node.parent.removeChild(node); 1423 } 1424 break; 1425 case ELEMENT_NODE: 1426 if (!config.namespaceDeclarations) 1427 { 1428 DomNamedNodeMap attrs = 1429 (DomNamedNodeMap) node.getAttributes(); 1430 boolean aro = attrs.readonly; 1431 attrs.readonly = false; // Ensure we can delete if necessary 1432 int len = attrs.getLength(); 1433 for (int i = 0; i < len; i++) 1434 { 1435 Node attr = attrs.item(i); 1436 String namespace = attr.getNamespaceURI(); 1437 if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespace)) 1438 { 1439 attrs.removeNamedItemNS(namespace, 1440 attr.getLocalName()); 1441 i--; 1442 len--; 1443 } 1444 } 1445 attrs.readonly = aro; 1446 } 1447 break; 1448 } 1449 } 1450 for (DomNode ctx = node.first; ctx != null; ) 1451 { 1452 DomNode ctxNext = ctx.next; 1453 normalizeNode(ctx); 1454 ctx = ctxNext; 1455 } 1456 } 1457 renameNode(Node n, String namespaceURI, String qualifiedName)1458 public Node renameNode(Node n, String namespaceURI, String qualifiedName) 1459 throws DOMException 1460 { 1461 if (n instanceof DomNsNode) 1462 { 1463 DomNsNode src = (DomNsNode) n; 1464 if (src == null) 1465 { 1466 throw new DomDOMException(DOMException.NOT_FOUND_ERR); 1467 } 1468 if (src.owner != this) 1469 { 1470 throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR, 1471 null, src, 0); 1472 } 1473 boolean xml11 = "1.1".equals(version); 1474 checkName(qualifiedName, xml11); 1475 int ci = qualifiedName.indexOf(':'); 1476 if ("".equals(namespaceURI)) 1477 { 1478 namespaceURI = null; 1479 } 1480 if (namespaceURI != null) 1481 { 1482 checkNCName(qualifiedName, xml11); 1483 String prefix = (ci == -1) ? "" : 1484 qualifiedName.substring(0, ci); 1485 if (XMLConstants.XML_NS_PREFIX.equals(prefix) && 1486 !XMLConstants.XML_NS_URI.equals(namespaceURI)) 1487 { 1488 throw new DomDOMException(DOMException.NAMESPACE_ERR, 1489 "xml namespace must be " + 1490 XMLConstants.XML_NS_URI, src, 0); 1491 } 1492 else if (src.nodeType == ATTRIBUTE_NODE && 1493 (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) || 1494 XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName)) && 1495 !XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) 1496 { 1497 throw new DomDOMException(DOMException.NAMESPACE_ERR, 1498 "xmlns namespace must be " + 1499 XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0); 1500 } 1501 if (XMLConstants.XML_NS_URI.equals(namespaceURI) && 1502 !XMLConstants.XML_NS_PREFIX.equals(prefix)) 1503 { 1504 throw new DomDOMException(DOMException.NAMESPACE_ERR, 1505 "xml namespace must be " + 1506 XMLConstants.XML_NS_URI, src, 0); 1507 } 1508 else if (src.nodeType == ATTRIBUTE_NODE && 1509 XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI) && 1510 !(XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) || 1511 XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName))) 1512 { 1513 throw new DomDOMException(DOMException.NAMESPACE_ERR, 1514 "xmlns namespace must be " + 1515 XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0); 1516 } 1517 1518 } 1519 src.setNodeName(qualifiedName); 1520 src.setNamespaceURI(namespaceURI); 1521 src.notifyUserDataHandlers(UserDataHandler.NODE_RENAMED, src, src); 1522 // TODO MutationNameEvents 1523 // DOMElementNameChanged or DOMAttributeNameChanged 1524 return src; 1525 } 1526 throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, n, 0); 1527 } 1528 1529 // -- XPathEvaluator -- 1530 createExpression(String expression, XPathNSResolver resolver)1531 public XPathExpression createExpression(String expression, 1532 XPathNSResolver resolver) 1533 throws XPathException, DOMException 1534 { 1535 return new DomXPathExpression(this, expression, resolver); 1536 } 1537 createNSResolver(Node nodeResolver)1538 public XPathNSResolver createNSResolver(Node nodeResolver) 1539 { 1540 return new DomXPathNSResolver(nodeResolver); 1541 } 1542 evaluate(String expression, Node contextNode, XPathNSResolver resolver, short type, Object result)1543 public Object evaluate(String expression, 1544 Node contextNode, 1545 XPathNSResolver resolver, 1546 short type, 1547 Object result) 1548 throws XPathException, DOMException 1549 { 1550 XPathExpression xpe = 1551 new DomXPathExpression(this, expression, resolver); 1552 return xpe.evaluate(contextNode, type, result); 1553 } 1554 1555 } 1556