1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.xml.xpath;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import javax.xml.namespace.QName;
22 import javax.xml.transform.Source;
23 import javax.xml.transform.TransformerException;
24 import javax.xml.transform.dom.DOMSource;
25 import javax.xml.transform.sax.SAXSource;
26 import javax.xml.transform.stream.StreamSource;
27 import javax.xml.xpath.XPath;
28 import javax.xml.xpath.XPathConstants;
29 import javax.xml.xpath.XPathFactory;
30 import javax.xml.xpath.XPathFactoryConfigurationException;
31
32 import org.w3c.dom.DOMException;
33 import org.w3c.dom.Element;
34 import org.w3c.dom.Node;
35 import org.w3c.dom.NodeList;
36 import org.xml.sax.InputSource;
37
38 import org.springframework.xml.namespace.SimpleNamespaceContext;
39 import org.springframework.xml.transform.TraxUtils;
40
41
42
43
44
45
46
47
48
49
50 public class Jaxp13XPathTemplate extends AbstractXPathTemplate {
51
52 private XPathFactory xpathFactory;
53
54 public Jaxp13XPathTemplate() {
55 this(XPathFactory.DEFAULT_OBJECT_MODEL_URI);
56 }
57
58 public Jaxp13XPathTemplate(String xpathFactoryUri) {
59 try {
60 xpathFactory = XPathFactory.newInstance(xpathFactoryUri);
61 }
62 catch (XPathFactoryConfigurationException ex) {
63 throw new XPathException("Could not create XPathFactory", ex);
64 }
65 }
66
67 public boolean evaluateAsBoolean(String expression, Source context) throws XPathException {
68 Boolean result = (Boolean) evaluate(expression, context, XPathConstants.BOOLEAN);
69 return result != null && result.booleanValue();
70 }
71
72 public Node evaluateAsNode(String expression, Source context) throws XPathException {
73 return (Node) evaluate(expression, context, XPathConstants.NODE);
74 }
75
76 public List evaluateAsNodeList(String expression, Source context) throws XPathException {
77 NodeList result = (NodeList) evaluate(expression, context, XPathConstants.NODESET);
78 List nodes = new ArrayList(result.getLength());
79 for (int i = 0; i < result.getLength(); i++) {
80 nodes.add(result.item(i));
81 }
82 return nodes;
83 }
84
85 public double evaluateAsDouble(String expression, Source context) throws XPathException {
86 Double result = (Double) evaluate(expression, context, XPathConstants.NUMBER);
87 return result != null ? result.doubleValue() : Double.NaN;
88 }
89
90 public String evaluateAsString(String expression, Source context) throws XPathException {
91 return (String) evaluate(expression, context, XPathConstants.STRING);
92 }
93
94 public Object evaluateAsObject(String expression, Source context, NodeMapper nodeMapper) throws XPathException {
95 Node node = evaluateAsNode(expression, context);
96 if (node != null) {
97 try {
98 return nodeMapper.mapNode(node, 0);
99 }
100 catch (DOMException ex) {
101 throw new XPathException("Mapping resulted in DOMException", ex);
102 }
103 }
104 else {
105 return null;
106 }
107 }
108
109 public List evaluate(String expression, Source context, NodeMapper nodeMapper) throws XPathException {
110 NodeList nodes = (NodeList) evaluate(expression, context, XPathConstants.NODESET);
111 List results = new ArrayList(nodes.getLength());
112 for (int i = 0; i < nodes.getLength(); i++) {
113 try {
114 results.add(nodeMapper.mapNode(nodes.item(i), i));
115 }
116 catch (DOMException ex) {
117 throw new XPathException("Mapping resulted in DOMException", ex);
118 }
119 }
120 return results;
121 }
122
123 private Object evaluate(String expression, Source context, QName returnType) throws XPathException {
124 XPath xpath = xpathFactory.newXPath();
125 if (getNamespaces() != null && !getNamespaces().isEmpty()) {
126 SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
127 namespaceContext.setBindings(getNamespaces());
128 xpath.setNamespaceContext(namespaceContext);
129 }
130 try {
131 if (TraxUtils.isStaxSource(context)) {
132 Element element = getRootElement(context);
133 return xpath.evaluate(expression, element, returnType);
134 }
135 else if (context instanceof SAXSource) {
136 SAXSource saxSource = (SAXSource) context;
137 return xpath.evaluate(expression, saxSource.getInputSource(), returnType);
138 }
139 else if (context instanceof DOMSource) {
140 DOMSource domSource = (DOMSource) context;
141 return xpath.evaluate(expression, domSource.getNode(), returnType);
142 }
143 else if (context instanceof StreamSource) {
144 StreamSource streamSource = (StreamSource) context;
145 InputSource inputSource;
146 if (streamSource.getInputStream() != null) {
147 inputSource = new InputSource(streamSource.getInputStream());
148 }
149 else if (streamSource.getReader() != null) {
150 inputSource = new InputSource(streamSource.getReader());
151 }
152 else {
153 throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader");
154 }
155 return xpath.evaluate(expression, inputSource, returnType);
156 }
157 else {
158 throw new IllegalArgumentException("context type unknown");
159 }
160 }
161 catch (javax.xml.xpath.XPathException ex) {
162 throw new XPathException("Could not evaluate XPath expression [" + expression + "]", ex);
163 }
164 catch (TransformerException ex) {
165 throw new XPathException("Could not transform context to DOM Node", ex);
166 }
167 }
168
169 }