1 package org.jaxen.dom;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 import javax.xml.parsers.DocumentBuilder;
52 import javax.xml.parsers.DocumentBuilderFactory;
53 import javax.xml.parsers.ParserConfigurationException;
54
55 import java.io.IOException;
56 import java.util.HashMap;
57 import java.util.Iterator;
58 import java.util.NoSuchElementException;
59
60 import org.jaxen.DefaultNavigator;
61 import org.jaxen.FunctionCallException;
62 import org.jaxen.Navigator;
63 import org.jaxen.XPath;
64 import org.jaxen.JaxenConstants;
65 import org.w3c.dom.Attr;
66 import org.w3c.dom.Document;
67 import org.w3c.dom.NamedNodeMap;
68 import org.w3c.dom.Node;
69 import org.w3c.dom.NodeList;
70 import org.w3c.dom.ProcessingInstruction;
71 import org.xml.sax.SAXException;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public class DocumentNavigator extends DefaultNavigator
98 {
99
100
101
102
103
104
105 private static final long serialVersionUID = 8460943068889528115L;
106
107 private final static DocumentNavigator SINGLETON = new DocumentNavigator();
108
109
110
111
112
113
114
115
116
117
118
119 public DocumentNavigator ()
120 {
121 }
122
123
124
125
126
127
128
129 public static Navigator getInstance ()
130 {
131 return SINGLETON;
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 public Iterator getChildAxisIterator (Object contextNode)
148 {
149 Node node = (Node) contextNode;
150
151 if ( node.getNodeType() == Node.ELEMENT_NODE || node.getNodeType() == Node.DOCUMENT_NODE)
152 {
153 return new NodeIterator ((Node)contextNode) {
154 protected Node getFirstNode (Node node)
155 {
156 return node.getFirstChild();
157 }
158 protected Node getNextNode (Node node)
159 {
160 return node.getNextSibling();
161 }
162 };
163 }
164
165 return JaxenConstants.EMPTY_ITERATOR;
166
167 }
168
169
170
171
172
173
174
175
176 public Iterator getParentAxisIterator (Object contextNode)
177 {
178 Node node = (Node)contextNode;
179
180 if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
181 return new NodeIterator (node) {
182 protected Node getFirstNode (Node n)
183 {
184
185
186 return ((Attr)n).getOwnerElement();
187 }
188 protected Node getNextNode (Node n) {
189 return null;
190 }
191 };
192 } else {
193 return new NodeIterator (node) {
194 protected Node getFirstNode (Node n)
195 {
196 return n.getParentNode();
197 }
198 protected Node getNextNode (Node n) {
199 return null;
200 }
201 };
202 }
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216 public Object getParentNode(Object child) {
217 Node node = (Node) child;
218 if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
219 return ((Attr) node).getOwnerElement();
220 }
221 return node.getParentNode();
222 }
223
224
225
226
227
228
229
230
231 public Iterator getFollowingSiblingAxisIterator (Object contextNode)
232 {
233 return new NodeIterator ((Node)contextNode) {
234 protected Node getFirstNode (Node node)
235 {
236 return getNextNode(node);
237 }
238 protected Node getNextNode (Node node) {
239 return node.getNextSibling();
240 }
241 };
242 }
243
244
245
246
247
248
249
250
251 public Iterator getPrecedingSiblingAxisIterator (Object contextNode)
252 {
253 return new NodeIterator ((Node)contextNode) {
254 protected Node getFirstNode (Node node)
255 {
256 return getNextNode(node);
257 }
258 protected Node getNextNode (Node node) {
259 return node.getPreviousSibling();
260 }
261 };
262 }
263
264
265
266
267
268
269
270
271 public Iterator getFollowingAxisIterator (Object contextNode)
272 {
273 return new NodeIterator ((Node)contextNode) {
274 protected Node getFirstNode (Node node)
275 {
276 if (node == null) {
277 return null;
278 }
279 else {
280 Node sibling = node.getNextSibling();
281 if (sibling == null) {
282 return getFirstNode(node.getParentNode());
283 }
284 else {
285 return sibling;
286 }
287 }
288 }
289 protected Node getNextNode (Node node) {
290 if (node == null) {
291 return null;
292 }
293 else {
294 Node n = node.getFirstChild();
295 if (n == null) n = node.getNextSibling();
296 if (n == null) return getFirstNode(node.getParentNode());
297 else return n;
298 }
299 }
300 };
301 }
302
303
304
305
306
307
308
309
310 public Iterator getAttributeAxisIterator (Object contextNode)
311 {
312 if (isElement(contextNode)) {
313 return new AttributeIterator((Node)contextNode);
314 }
315 else {
316 return JaxenConstants.EMPTY_ITERATOR;
317 }
318 }
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347 public Iterator getNamespaceAxisIterator (Object contextNode)
348 {
349
350 if (isElement(contextNode)) {
351
352 HashMap nsMap = new HashMap();
353
354
355
356
357 for (Node n = (Node) contextNode;
358 n != null;
359 n = n.getParentNode()) {
360
361
362 String myNamespace = n.getNamespaceURI();
363 if (myNamespace != null && ! "".equals(myNamespace)) {
364 String myPrefix = n.getPrefix();
365 if (!nsMap.containsKey(myPrefix)) {
366 NamespaceNode ns = new NamespaceNode((Node) contextNode, myPrefix, myNamespace);
367 nsMap.put(myPrefix, ns);
368 }
369 }
370
371 if (n.hasAttributes()) {
372 NamedNodeMap atts = n.getAttributes();
373 int length = atts.getLength();
374
375 for (int i = 0; i < length; i++) {
376 Attr att = (Attr) atts.item(i);
377
378 String attributeNamespace = att.getNamespaceURI();
379 if ("http://www.w3.org/2000/xmlns/".equals(attributeNamespace)) {
380 }
381 else if (attributeNamespace != null) {
382 String prefix = att.getPrefix();
383 NamespaceNode ns =
384 new NamespaceNode((Node)contextNode, prefix, attributeNamespace);
385
386 if (!nsMap.containsKey(prefix)) nsMap.put(prefix, ns);
387
388 }
389 }
390
391
392 for (int i = 0; i < length; i++) {
393 Attr att = (Attr) atts.item(i);
394
395 String attributeNamespace = att.getNamespaceURI();
396 if ("http://www.w3.org/2000/xmlns/".equals(attributeNamespace)) {
397 NamespaceNode ns =
398 new NamespaceNode( (Node)contextNode, att);
399
400 String name = ns.getNodeName();
401 if (!nsMap.containsKey(name)) nsMap.put(name, ns);
402 }
403 }
404
405 }
406
407 }
408
409
410 nsMap.put("xml",
411 new
412 NamespaceNode((Node)contextNode,
413 "xml",
414 "http://www.w3.org/XML/1998/namespace"));
415
416
417
418 NamespaceNode defaultNS = (NamespaceNode)nsMap.get("");
419 if (defaultNS != null && defaultNS.getNodeValue().length() == 0) {
420 nsMap.remove("");
421 }
422 return nsMap.values().iterator();
423 }
424 else {
425 return JaxenConstants.EMPTY_ITERATOR;
426 }
427 }
428
429
430
431
432
433
434
435
436 public XPath parseXPath (String xpath) throws org.jaxen.saxpath.SAXPathException
437 {
438 return new DOMXPath(xpath);
439 }
440
441
442
443
444
445
446
447 public Object getDocumentNode (Object contextNode)
448 {
449 if (isDocument(contextNode)) return contextNode;
450 else return ((Node)contextNode).getOwnerDocument();
451 }
452
453
454
455
456
457
458
459
460
461
462
463 public String getElementNamespaceUri (Object element)
464 {
465 try {
466 Node node = (Node) element;
467 if (node.getNodeType() == Node.ELEMENT_NODE) {
468 return node.getNamespaceURI();
469 }
470 }
471 catch (ClassCastException ex) {
472 }
473 return null;
474 }
475
476
477
478
479
480
481
482
483
484 public String getElementName (Object element)
485 {
486 if (isElement(element)) {
487 String name = ((Node)element).getLocalName();
488 if (name == null) name = ((Node)element).getNodeName();
489 return name;
490 }
491 return null;
492 }
493
494
495
496
497
498
499
500
501
502 public String getElementQName (Object element)
503 {
504 try {
505 Node node = (Node) element;
506 if (node.getNodeType() == Node.ELEMENT_NODE) {
507 return node.getNodeName();
508 }
509 }
510 catch (ClassCastException ex) {
511 }
512 return null;
513 }
514
515
516
517
518
519
520
521
522
523
524 public String getAttributeNamespaceUri (Object attribute)
525 {
526 try {
527 Node node = (Node) attribute;
528 if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
529 return node.getNamespaceURI();
530 }
531 }
532 catch (ClassCastException ex) {
533 }
534 return null;
535 }
536
537
538
539
540
541
542
543
544
545 public String getAttributeName (Object attribute)
546 {
547 if (isAttribute(attribute)) {
548 String name = ((Node)attribute).getLocalName();
549 if (name == null) name = ((Node)attribute).getNodeName();
550 return name;
551 }
552 return null;
553 }
554
555
556
557
558
559
560
561
562
563
564 public String getAttributeQName (Object attribute)
565 {
566 try {
567 Node node = (Node) attribute;
568 if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
569 return node.getNodeName();
570 }
571 }
572 catch (ClassCastException ex) {
573 }
574 return null;
575 }
576
577
578
579
580
581
582
583
584 public boolean isDocument (Object object)
585 {
586 return (object instanceof Node) &&
587 (((Node)object).getNodeType() == Node.DOCUMENT_NODE);
588 }
589
590
591
592
593
594
595
596
597 public boolean isNamespace (Object object)
598 {
599 return (object instanceof NamespaceNode);
600 }
601
602
603
604
605
606
607
608
609 public boolean isElement (Object object)
610 {
611 return (object instanceof Node) &&
612 (((Node)object).getNodeType() == Node.ELEMENT_NODE);
613 }
614
615
616
617
618
619
620
621
622
623
624 public boolean isAttribute (Object object)
625 {
626 return (object instanceof Node) &&
627 (((Node)object).getNodeType() == Node.ATTRIBUTE_NODE)
628 && ! "http://www.w3.org/2000/xmlns/".equals(((Node) object).getNamespaceURI());
629 }
630
631
632
633
634
635
636
637
638 public boolean isComment (Object object)
639 {
640 return (object instanceof Node) &&
641 (((Node)object).getNodeType() == Node.COMMENT_NODE);
642 }
643
644
645
646
647
648
649
650
651 public boolean isText (Object object)
652 {
653 if (object instanceof Node) {
654 switch (((Node)object).getNodeType()) {
655 case Node.TEXT_NODE:
656 case Node.CDATA_SECTION_NODE:
657 return true;
658 default:
659 return false;
660 }
661 } else {
662 return false;
663 }
664 }
665
666
667
668
669
670
671
672
673 public boolean isProcessingInstruction (Object object)
674 {
675 return (object instanceof Node) &&
676 (((Node)object).getNodeType() == Node.PROCESSING_INSTRUCTION_NODE);
677 }
678
679
680
681
682
683
684
685
686
687 public String getElementStringValue (Object object)
688 {
689 if (isElement(object)) {
690 return getStringValue((Node)object, new StringBuffer()).toString();
691 }
692 else {
693 return null;
694 }
695 }
696
697
698
699
700
701
702
703
704
705 private StringBuffer getStringValue (Node node, StringBuffer buffer)
706 {
707 if (isText(node)) {
708 buffer.append(node.getNodeValue());
709 } else {
710 NodeList children = node.getChildNodes();
711 int length = children.getLength();
712 for (int i = 0; i < length; i++) {
713 getStringValue(children.item(i), buffer);
714 }
715 }
716 return buffer;
717 }
718
719
720
721
722
723
724
725
726
727 public String getAttributeStringValue (Object object)
728 {
729 if (isAttribute(object)) return ((Node)object).getNodeValue();
730 else return null;
731 }
732
733
734
735
736
737
738
739
740 public String getTextStringValue (Object object)
741 {
742 if (isText(object)) return ((Node)object).getNodeValue();
743 else return null;
744 }
745
746
747
748
749
750
751
752
753 public String getCommentStringValue (Object object)
754 {
755 if (isComment(object)) return ((Node)object).getNodeValue();
756 else return null;
757 }
758
759
760
761
762
763
764
765
766
767 public String getNamespaceStringValue (Object object)
768 {
769 if (isNamespace(object)) return ((NamespaceNode)object).getNodeValue();
770 else return null;
771 }
772
773
774
775
776
777
778
779
780 public String getNamespacePrefix (Object object)
781 {
782 if (isNamespace(object)) return ((NamespaceNode)object).getLocalName();
783 else return null;
784 }
785
786
787
788
789
790
791
792
793
794 public String translateNamespacePrefixToUri (String prefix, Object element)
795 {
796 Iterator it = getNamespaceAxisIterator(element);
797 while (it.hasNext()) {
798 NamespaceNode ns = (NamespaceNode)it.next();
799 if (prefix.equals(ns.getNodeName())) return ns.getNodeValue();
800 }
801 return null;
802 }
803
804
805
806
807
808
809
810
811
812
813
814 public Object getDocument(String uri) throws FunctionCallException
815 {
816 try
817 {
818
819
820 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
821 factory.setNamespaceAware(true);
822 DocumentBuilder builder = factory.newDocumentBuilder();
823 return builder.parse( uri );
824 }
825 catch (ParserConfigurationException e) {
826 throw new FunctionCallException("JAXP setup error in document() function: " + e.getMessage(), e);
827 }
828 catch (SAXException e) {
829 throw new FunctionCallException("XML error in document() function: " + e.getMessage(), e);
830 }
831 catch (IOException e) {
832 throw new FunctionCallException("I/O error in document() function: " + e.getMessage(), e);
833 }
834
835 }
836
837
838
839
840
841
842
843
844
845 public String getProcessingInstructionTarget(Object obj)
846 {
847 if (isProcessingInstruction(obj)) {
848 ProcessingInstruction pi = (ProcessingInstruction) obj;
849 return pi.getTarget();
850 }
851 throw new ClassCastException(obj + " is not a processing instruction");
852 }
853
854
855
856
857
858
859
860
861
862 public String getProcessingInstructionData(Object obj)
863 {
864 if (isProcessingInstruction(obj)) {
865 ProcessingInstruction pi = (ProcessingInstruction) obj;
866 return pi.getData();
867 }
868 throw new ClassCastException(obj + " is not a processing instruction");
869 }
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888 abstract class NodeIterator
889 implements Iterator
890 {
891
892
893
894
895
896
897
898 public NodeIterator (Node contextNode)
899 {
900 node = getFirstNode(contextNode);
901 while (!isXPathNode(node)) {
902 node = getNextNode(node);
903 }
904 }
905
906 public boolean hasNext ()
907 {
908 return (node != null);
909 }
910
911 public Object next ()
912 {
913 if (node == null) throw new NoSuchElementException();
914 Node ret = node;
915 node = getNextNode(node);
916 while (!isXPathNode(node)) {
917 node = getNextNode(node);
918 }
919 return ret;
920 }
921
922 public void remove ()
923 {
924 throw new UnsupportedOperationException();
925 }
926
927
928
929
930
931
932
933
934
935
936
937
938 protected abstract Node getFirstNode (Node contextNode);
939
940
941
942
943
944
945
946
947
948
949
950
951
952 protected abstract Node getNextNode (Node contextNode);
953
954
955
956
957
958
959
960
961 private boolean isXPathNode (Node node)
962 {
963
964 if (node == null) return true;
965
966 switch (node.getNodeType()) {
967 case Node.DOCUMENT_FRAGMENT_NODE:
968 case Node.DOCUMENT_TYPE_NODE:
969 case Node.ENTITY_NODE:
970 case Node.ENTITY_REFERENCE_NODE:
971 case Node.NOTATION_NODE:
972 return false;
973 default:
974 return true;
975 }
976 }
977
978 private Node node;
979 }
980
981
982
983
984
985
986
987
988
989
990
991 private static class AttributeIterator implements Iterator
992 {
993
994
995
996
997
998
999 AttributeIterator (Node parent)
1000 {
1001 this.map = parent.getAttributes();
1002 this.pos = 0;
1003 for (int i = this.map.getLength()-1; i >= 0; i--) {
1004 Node node = map.item(i);
1005 if (! "http://www.w3.org/2000/xmlns/".equals(node.getNamespaceURI())) {
1006 this.lastAttribute = i;
1007 break;
1008 }
1009 }
1010 }
1011
1012 public boolean hasNext ()
1013 {
1014 return pos <= lastAttribute;
1015 }
1016
1017 public Object next ()
1018 {
1019 Node attr = map.item(pos++);
1020 if (attr == null) throw new NoSuchElementException();
1021 else if ("http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI())) {
1022
1023
1024 return next();
1025 }
1026 else return attr;
1027 }
1028
1029 public void remove ()
1030 {
1031 throw new UnsupportedOperationException();
1032 }
1033
1034
1035 private NamedNodeMap map;
1036 private int pos;
1037 private int lastAttribute = -1;
1038
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 public Object getElementById(Object object, String elementId)
1062 {
1063 Document doc = (Document)getDocumentNode(object);
1064 if (doc != null) return doc.getElementById(elementId);
1065 else return null;
1066 }
1067
1068 }
1069
1070