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.io.InputStream;
20 import java.io.Reader;
21 import java.util.ArrayList;
22 import java.util.List;
23 import javax.xml.namespace.QName;
24 import javax.xml.stream.XMLEventReader;
25 import javax.xml.stream.XMLStreamException;
26 import javax.xml.stream.XMLStreamReader;
27 import javax.xml.transform.Source;
28 import javax.xml.transform.TransformerException;
29 import javax.xml.transform.dom.DOMResult;
30 import javax.xml.xpath.XPath;
31 import javax.xml.xpath.XPathConstants;
32 import javax.xml.xpath.XPathExpressionException;
33 import javax.xml.xpath.XPathFactory;
34 import javax.xml.xpath.XPathFactoryConfigurationException;
35
36 import org.springframework.util.xml.StaxUtils;
37 import org.springframework.xml.namespace.SimpleNamespaceContext;
38 import org.springframework.xml.transform.TransformerHelper;
39 import org.springframework.xml.transform.TraxUtils;
40
41 import org.w3c.dom.DOMException;
42 import org.w3c.dom.Document;
43 import org.w3c.dom.Element;
44 import org.w3c.dom.Node;
45 import org.w3c.dom.NodeList;
46 import org.xml.sax.InputSource;
47 import org.xml.sax.XMLReader;
48
49
50
51
52
53
54
55
56
57
58 public class Jaxp13XPathTemplate extends AbstractXPathTemplate {
59
60 private XPathFactory xpathFactory;
61
62 public Jaxp13XPathTemplate() {
63 this(XPathFactory.DEFAULT_OBJECT_MODEL_URI);
64 }
65
66 public Jaxp13XPathTemplate(String xpathFactoryUri) {
67 try {
68 xpathFactory = XPathFactory.newInstance(xpathFactoryUri);
69 }
70 catch (XPathFactoryConfigurationException ex) {
71 throw new XPathException("Could not create XPathFactory", ex);
72 }
73 }
74
75 public boolean evaluateAsBoolean(String expression, Source context) throws XPathException {
76 Boolean result = (Boolean) evaluate(expression, context, XPathConstants.BOOLEAN);
77 return result != null && result;
78 }
79
80 public Node evaluateAsNode(String expression, Source context) throws XPathException {
81 return (Node) evaluate(expression, context, XPathConstants.NODE);
82 }
83
84 public List<Node> evaluateAsNodeList(String expression, Source context) throws XPathException {
85 NodeList result = (NodeList) evaluate(expression, context, XPathConstants.NODESET);
86 List<Node> nodes = new ArrayList<Node>(result.getLength());
87 for (int i = 0; i < result.getLength(); i++) {
88 nodes.add(result.item(i));
89 }
90 return nodes;
91 }
92
93 public double evaluateAsDouble(String expression, Source context) throws XPathException {
94 Double result = (Double) evaluate(expression, context, XPathConstants.NUMBER);
95 return result != null ? result : Double.NaN;
96 }
97
98 public String evaluateAsString(String expression, Source context) throws XPathException {
99 return (String) evaluate(expression, context, XPathConstants.STRING);
100 }
101
102 public <T> T evaluateAsObject(String expression, Source context, NodeMapper<T> nodeMapper) throws XPathException {
103 Node node = evaluateAsNode(expression, context);
104 if (node != null) {
105 try {
106 return nodeMapper.mapNode(node, 0);
107 }
108 catch (DOMException ex) {
109 throw new XPathException("Mapping resulted in DOMException", ex);
110 }
111 }
112 else {
113 return null;
114 }
115 }
116
117 public <T> List<T> evaluate(String expression, Source context, NodeMapper<T> nodeMapper) throws XPathException {
118 NodeList nodes = (NodeList) evaluate(expression, context, XPathConstants.NODESET);
119 List<T> results = new ArrayList<T>(nodes.getLength());
120 for (int i = 0; i < nodes.getLength(); i++) {
121 try {
122 results.add(nodeMapper.mapNode(nodes.item(i), i));
123 }
124 catch (DOMException ex) {
125 throw new XPathException("Mapping resulted in DOMException", ex);
126 }
127 }
128 return results;
129 }
130
131 private Object evaluate(String expression, Source context, QName returnType) throws XPathException {
132 XPath xpath = createXPath();
133 if (getNamespaces() != null && !getNamespaces().isEmpty()) {
134 SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
135 namespaceContext.setBindings(getNamespaces());
136 xpath.setNamespaceContext(namespaceContext);
137 }
138 try {
139 EvaluationCallback callback = new EvaluationCallback(xpath, expression, returnType);
140 TraxUtils.doWithSource(context, callback);
141 return callback.result;
142 }
143 catch (javax.xml.xpath.XPathException ex) {
144 throw new XPathException("Could not evaluate XPath expression [" + expression + "]", ex);
145 }
146 catch (TransformerException ex) {
147 throw new XPathException("Could not transform context to DOM Node", ex);
148 }
149 catch (Exception ex) {
150 throw new XPathException(ex.getMessage(), ex);
151 }
152 }
153
154 private synchronized XPath createXPath() {
155 return xpathFactory.newXPath();
156 }
157
158 private static class EvaluationCallback implements TraxUtils.SourceCallback {
159
160 private final XPath xpath;
161
162 private final String expression;
163
164 private final QName returnType;
165
166 private final TransformerHelper transformerHelper = new TransformerHelper();
167
168 private Object result;
169
170 private EvaluationCallback(XPath xpath, String expression, QName returnType) {
171 this.xpath = xpath;
172 this.expression = expression;
173 this.returnType = returnType;
174 }
175
176 public void domSource(Node node) throws XPathExpressionException {
177 result = xpath.evaluate(expression, node, returnType);
178 }
179
180 public void saxSource(XMLReader reader, InputSource inputSource) throws XPathExpressionException {
181 inputSource(inputSource);
182 }
183
184 public void staxSource(XMLEventReader eventReader)
185 throws XPathExpressionException, XMLStreamException, TransformerException {
186 Element element = getRootElement(StaxUtils.createCustomStaxSource(eventReader));
187 domSource(element);
188 }
189
190 public void staxSource(XMLStreamReader streamReader) throws TransformerException, XPathExpressionException {
191 Element element = getRootElement(StaxUtils.createCustomStaxSource(streamReader));
192 domSource(element);
193 }
194
195 public void streamSource(InputStream inputStream) throws XPathExpressionException {
196 inputSource(new InputSource(inputStream));
197 }
198
199 public void streamSource(Reader reader) throws XPathExpressionException {
200 inputSource(new InputSource(reader));
201 }
202
203 public void source(String systemId) throws XPathExpressionException {
204 inputSource(new InputSource(systemId));
205 }
206
207 private void inputSource(InputSource inputSource) throws XPathExpressionException {
208 result = xpath.evaluate(expression, inputSource, returnType);
209 }
210
211 private Element getRootElement(Source source) throws TransformerException {
212 DOMResult domResult = new DOMResult();
213 transformerHelper.transform(source, domResult);
214 Document document = (Document) domResult.getNode();
215 return document.getDocumentElement();
216 }
217
218 }
219
220
221
222 }