1 package org.jaxen.dom; 2 3 63 64 import javax.xml.parsers.DocumentBuilder ; 65 import javax.xml.parsers.DocumentBuilderFactory ; 66 import javax.xml.parsers.ParserConfigurationException ; 67 68 import java.io.IOException ; 69 import java.util.HashMap ; 70 import java.util.Iterator ; 71 import java.util.NoSuchElementException ; 72 73 import org.jaxen.DefaultNavigator; 74 import org.jaxen.FunctionCallException; 75 import org.jaxen.Navigator; 76 import org.jaxen.XPath; 77 import org.jaxen.JaxenConstants; 78 import org.w3c.dom.Attr ; 79 import org.w3c.dom.Document ; 80 import org.w3c.dom.NamedNodeMap ; 81 import org.w3c.dom.Node ; 82 import org.w3c.dom.NodeList ; 83 import org.w3c.dom.ProcessingInstruction ; 84 import org.xml.sax.SAXException ; 85 86 110 public class DocumentNavigator extends DefaultNavigator 111 { 112 113 114 118 121 private final static DocumentNavigator SINGLETON = new DocumentNavigator(); 122 123 124 125 129 130 133 public DocumentNavigator () 134 { 135 } 136 137 138 143 public static Navigator getInstance () 144 { 145 return SINGLETON; 146 } 147 148 149 150 154 155 161 public Iterator getChildAxisIterator (Object contextNode) 162 { 163 return new NodeIterator ((Node )contextNode) { 164 protected Node getFirstNode (Node node) 165 { 166 return node.getFirstChild(); 167 } 168 protected Node getNextNode (Node node) 169 { 170 return node.getNextSibling(); 171 } 172 }; 173 } 174 175 176 182 public Iterator getParentAxisIterator (Object contextNode) 183 { 184 Node node = (Node )contextNode; 185 186 if (node.getNodeType() == Node.ATTRIBUTE_NODE) { 187 return new NodeIterator (node) { 188 protected Node getFirstNode (Node n) 189 { 190 return ((Attr )n).getOwnerElement(); 192 } 193 protected Node getNextNode (Node n) { 194 return null; 195 } 196 }; 197 } else { 198 return new NodeIterator (node) { 199 protected Node getFirstNode (Node n) 200 { 201 return n.getParentNode(); 202 } 203 protected Node getNextNode (Node n) { 204 return null; 205 } 206 }; 207 } 208 } 209 210 211 217 public Iterator getFollowingSiblingAxisIterator (Object contextNode) 218 { 219 return new NodeIterator ((Node )contextNode) { 220 protected Node getFirstNode (Node node) 221 { 222 return getNextNode(node); 223 } 224 protected Node getNextNode (Node node) { 225 return node.getNextSibling(); 226 } 227 }; 228 } 229 230 231 237 public Iterator getPrecedingSiblingAxisIterator (Object contextNode) 238 { 239 return new NodeIterator ((Node )contextNode) { 240 protected Node getFirstNode (Node node) 241 { 242 return getNextNode(node); 243 } 244 protected Node getNextNode (Node node) { 245 return node.getPreviousSibling(); 246 } 247 }; 248 } 249 250 251 257 public Iterator getFollowingAxisIterator (Object contextNode) 258 { 259 return new NodeIterator ((Node )contextNode) { 260 protected Node getFirstNode (Node node) 261 { 262 if (node == null) 263 return null; 264 else { 265 Node sibling = node.getNextSibling(); 266 if (sibling == null) 267 return getFirstNode(node.getParentNode()); 268 else 269 return sibling; 270 } 271 } 272 protected Node getNextNode (Node node) { 273 if (node == null) 274 return null; 275 else { 276 Node n = node.getFirstChild(); 277 if (n == null) 278 n = node.getNextSibling(); 279 if (n == null) 280 return getFirstNode(node.getParentNode()); 281 else 282 return n; 283 } 284 } 285 }; 286 } 287 288 289 295 public Iterator getAttributeAxisIterator (Object contextNode) 296 { 297 if (isElement(contextNode)) { 298 return new AttributeIterator((Node )contextNode); 299 } else { 300 return JaxenConstants.EMPTY_ITERATOR; 301 } 302 } 303 304 305 316 public Iterator getNamespaceAxisIterator (Object contextNode) 317 { 318 if (isElement(contextNode)) { 320 321 HashMap nsMap = new HashMap (); 322 323 for (Node n = (Node )contextNode; 327 n != null; 328 n = n.getParentNode()) { 329 330 if (n.hasAttributes()) { 332 NamedNodeMap atts = n.getAttributes(); 333 int length = atts.getLength(); 334 for (int i = 0; i < length; i++) { 335 Attr att = (Attr ) atts.item(i); 336 String attributeNamespace = att.getNamespaceURI(); 338 if ("http://www.w3.org/2000/xmlns/".equals(attributeNamespace)) { 339 NamespaceNode ns = 340 new NamespaceNode((Node )contextNode, att); 341 String name = ns.getNodeName(); 344 if (!nsMap.containsKey(name)) nsMap.put(name, ns); 345 } 346 else if (attributeNamespace != null) { 347 String prefix = att.getPrefix(); 348 NamespaceNode ns = 349 new NamespaceNode((Node )contextNode, prefix, attributeNamespace); 350 if (!nsMap.containsKey(prefix)) nsMap.put(prefix, ns); 353 354 } 355 } 356 } 357 358 String myNamespace = n.getNamespaceURI(); 360 if (myNamespace != null && ! "".equals(myNamespace)) { 361 String myPrefix = n.getPrefix(); 362 if (!nsMap.containsKey(myPrefix)) { 363 NamespaceNode ns = new NamespaceNode((Node ) contextNode, myPrefix, myNamespace); 364 nsMap.put(myPrefix, ns); 365 } 366 } 367 368 } 369 nsMap.put("xml", 372 new 373 NamespaceNode((Node )contextNode, 374 "xml", 375 "http://www.w3.org/XML/1998/namespace")); 376 377 NamespaceNode defaultNS = (NamespaceNode)nsMap.get(""); 380 if (defaultNS != null && defaultNS.getNodeValue().length() == 0) 381 nsMap.remove(""); 382 return nsMap.values().iterator(); 383 } else { 384 return JaxenConstants.EMPTY_ITERATOR; 385 } 386 } 387 388 391 public XPath parseXPath (String xpath) throws org.jaxen.saxpath.SAXPathException 392 { 393 return new DOMXPath(xpath); 394 } 395 396 402 public Object getDocumentNode (Object contextNode) 403 { 404 if (isDocument(contextNode)) return contextNode; 405 else return ((Node )contextNode).getOwnerDocument(); 406 } 407 408 409 416 public String getElementNamespaceUri (Object object) 417 { 418 String uri = ((Node )object).getNamespaceURI(); 419 return uri; 420 } 421 422 423 430 public String getElementName (Object object) 431 { 432 String name = ((Node )object).getLocalName(); 433 if (name == null) name = ((Node )object).getNodeName(); 434 return name; 435 } 436 437 438 445 public String getElementQName (Object object) 446 { 447 String qname = ((Node )object).getNodeName(); 448 if (qname == null) qname = ((Node )object).getLocalName(); 449 return qname; 450 } 451 452 453 458 public String getAttributeNamespaceUri (Object object) 459 { 460 String uri = ((Node )object).getNamespaceURI(); 461 return uri; 462 } 463 464 465 472 public String getAttributeName (Object object) 473 { 474 String name = ((Node )object).getLocalName(); 475 if (name == null) name = ((Node )object).getNodeName(); 476 return name; 477 } 478 479 480 487 public String getAttributeQName (Object object) 488 { 489 String qname = ((Node )object).getNodeName(); 490 if (qname == null) qname = ((Node )object).getLocalName(); 491 return qname; 492 } 493 494 495 501 public boolean isDocument (Object object) 502 { 503 return (object instanceof Node ) && 504 (((Node )object).getNodeType() == Node.DOCUMENT_NODE); 505 } 506 507 508 514 public boolean isNamespace (Object object) 515 { 516 return (object instanceof NamespaceNode); 517 } 518 519 520 526 public boolean isElement (Object object) 527 { 528 return (object instanceof Node ) && 529 (((Node )object).getNodeType() == Node.ELEMENT_NODE); 530 } 531 532 533 541 public boolean isAttribute (Object object) 542 { 543 return (object instanceof Node ) && 544 (((Node )object).getNodeType() == Node.ATTRIBUTE_NODE) 545 && ! "http://www.w3.org/2000/xmlns/".equals(((Node ) object).getNamespaceURI()); 546 } 547 548 549 555 public boolean isComment (Object object) 556 { 557 return (object instanceof Node ) && 558 (((Node )object).getNodeType() == Node.COMMENT_NODE); 559 } 560 561 562 568 public boolean isText (Object object) 569 { 570 if (object instanceof Node ) { 571 switch (((Node )object).getNodeType()) { 572 case Node.TEXT_NODE: 573 case Node.CDATA_SECTION_NODE: 574 return true; 575 default: 576 return false; 577 } 578 } else { 579 return false; 580 } 581 } 582 583 584 590 public boolean isProcessingInstruction (Object object) 591 { 592 return (object instanceof Node ) && 593 (((Node )object).getNodeType() == Node.PROCESSING_INSTRUCTION_NODE); 594 } 595 596 597 604 public String getElementStringValue (Object object) 605 { 606 if (isElement(object)) { 607 return getStringValue((Node )object, new StringBuffer ()).toString(); 608 } 609 else { 610 return null; 611 } 612 } 613 614 615 622 private StringBuffer getStringValue (Node node, StringBuffer buffer) 623 { 624 if (isText(node)) { 625 buffer.append(node.getNodeValue()); 626 } else { 627 NodeList children = node.getChildNodes(); 628 int length = children.getLength(); 629 for (int i = 0; i < length; i++) { 630 getStringValue(children.item(i), buffer); 631 } 632 } 633 return buffer; 634 } 635 636 637 644 public String getAttributeStringValue (Object object) 645 { 646 if (isAttribute(object)) return ((Node )object).getNodeValue(); 647 else return null; 648 } 649 650 651 657 public String getTextStringValue (Object object) 658 { 659 if (isText(object)) return ((Node )object).getNodeValue(); 660 else return null; 661 } 662 663 664 671 public String getCommentStringValue (Object object) 672 { 673 if (isComment(object)) return ((Node )object).getNodeValue(); 674 else return null; 675 } 676 677 678 685 public String getNamespaceStringValue (Object object) 686 { 687 if (isNamespace(object)) return ((NamespaceNode)object).getNodeValue(); 688 else return null; 689 } 690 691 698 public String getNamespacePrefix (Object object) 699 { 700 if (isNamespace(object)) return ((NamespaceNode)object).getLocalName(); 701 else return null; 702 } 703 704 707 public String translateNamespacePrefixToUri (String prefix, Object element) 708 { 709 Iterator it = getNamespaceAxisIterator(element); 710 while (it.hasNext()) { 711 NamespaceNode ns = (NamespaceNode)it.next(); 712 if (prefix.equals(ns.getNodeName())) return ns.getNodeValue(); 713 } 714 return null; 715 } 716 717 725 public Object getDocument(String uri) throws FunctionCallException 726 { 727 try 728 { 729 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 730 factory.setNamespaceAware(true); 731 DocumentBuilder builder = factory.newDocumentBuilder(); 732 return builder.parse( uri ); 733 } 734 catch (ParserConfigurationException e) { 735 throw new FunctionCallException("JAXP setup error in document() function: " + e.getMessage(), e); 736 } 737 catch (SAXException e) { 738 throw new FunctionCallException("XML error in document() function: " + e.getMessage(), e); 739 } 740 catch (IOException e) { 741 throw new FunctionCallException("I/O error in document() function: " + e.getMessage(), e); 742 } 743 744 } 745 746 public String getProcessingInstructionTarget(Object obj) 747 { 748 ProcessingInstruction pi = (ProcessingInstruction ) obj; 749 750 return pi.getTarget(); 751 } 752 753 public String getProcessingInstructionData(Object obj) 754 { 755 ProcessingInstruction pi = (ProcessingInstruction ) obj; 756 757 return pi.getData(); 758 } 759 760 761 765 766 770 777 abstract class NodeIterator 778 implements Iterator 779 { 780 781 782 787 public NodeIterator (Node contextNode) 788 { 789 node = getFirstNode(contextNode); 790 while (!isXPathNode(node)) 791 node = getNextNode(node); 792 } 793 794 795 798 public boolean hasNext () 799 { 800 return (node != null); 801 } 802 803 804 807 public Object next () 808 { 809 if (node == null) throw new NoSuchElementException (); 810 Node ret = node; 811 node = getNextNode(node); 812 while (!isXPathNode(node)) { 813 node = getNextNode(node); 814 } 815 return ret; 816 } 817 818 819 822 public void remove () 823 { 824 throw new UnsupportedOperationException (); 825 } 826 827 828 838 protected abstract Node getFirstNode (Node contextNode); 839 840 841 852 protected abstract Node getNextNode (Node contextNode); 853 854 855 862 private boolean isXPathNode (Node node) 863 { 864 if (node == null) 866 return true; 867 868 switch (node.getNodeType()) { 869 case Node.DOCUMENT_FRAGMENT_NODE: 870 case Node.DOCUMENT_TYPE_NODE: 871 case Node.ENTITY_NODE: 872 case Node.ENTITY_REFERENCE_NODE: 873 case Node.NOTATION_NODE: 874 return false; 875 default: 876 return true; 877 } 878 } 879 880 private Node node; 881 } 882 883 884 885 889 890 893 private static class AttributeIterator implements Iterator 894 { 895 896 901 AttributeIterator (Node parent) 902 { 903 this.map = parent.getAttributes(); 904 this.pos = 0; 905 for (int i = this.map.getLength()-1; i >= 0; i--) { 906 Node node = map.item(i); 907 if (! "http://www.w3.org/2000/xmlns/".equals(node.getNamespaceURI())) { 908 this.lastAttribute = i; 909 break; 910 } 911 } 912 } 913 914 915 918 public boolean hasNext () 919 { 920 return pos <= lastAttribute; 921 } 922 923 924 927 public Object next () 928 { 929 Node attr = map.item(pos++); 930 if (attr == null) throw new NoSuchElementException (); 931 else if ("http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI())) { 932 return next(); 935 } 936 else return attr; 937 } 938 939 940 943 public void remove () 944 { 945 throw new UnsupportedOperationException (); 946 } 947 948 949 private NamedNodeMap map; 950 private int pos; 951 private int lastAttribute = -1; 952 953 } 954 955 972 public Object getElementById(Object object, String elementId) 973 { 974 Document doc = (Document )getDocumentNode(object); 975 if (doc != null) return doc.getElementById(elementId); 976 else return null; 977 } 978 979 } 980 981 | Popular Tags |