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