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 java.util.Map;
22 import javax.xml.namespace.QName;
23 import javax.xml.xpath.XPath;
24 import javax.xml.xpath.XPathConstants;
25 import javax.xml.xpath.XPathExpressionException;
26 import javax.xml.xpath.XPathFactory;
27
28 import org.springframework.xml.namespace.SimpleNamespaceContext;
29
30 import org.w3c.dom.DOMException;
31 import org.w3c.dom.Node;
32 import org.w3c.dom.NodeList;
33
34
35
36
37
38
39
40
41 abstract class Jaxp13XPathExpressionFactory {
42
43 private static XPathFactory xpathFactory = XPathFactory.newInstance();
44
45
46
47
48
49
50
51
52 static XPathExpression createXPathExpression(String expression) {
53 try {
54 XPath xpath = createXPath();
55 javax.xml.xpath.XPathExpression xpathExpression = xpath.compile(expression);
56 return new Jaxp13XPathExpression(xpathExpression);
57 }
58 catch (XPathExpressionException ex) {
59 throw new org.springframework.xml.xpath.XPathParseException(
60 "Could not compile [" + expression + "] to a XPathExpression: " + ex.getMessage(), ex);
61 }
62 }
63
64
65
66
67
68
69
70
71
72 public static XPathExpression createXPathExpression(String expression, Map<String, String> namespaces) {
73 try {
74 XPath xpath = createXPath();
75 SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
76 namespaceContext.setBindings(namespaces);
77 xpath.setNamespaceContext(namespaceContext);
78 javax.xml.xpath.XPathExpression xpathExpression = xpath.compile(expression);
79 return new Jaxp13XPathExpression(xpathExpression);
80 }
81 catch (XPathExpressionException ex) {
82 throw new org.springframework.xml.xpath.XPathParseException(
83 "Could not compile [" + expression + "] to a XPathExpression: " + ex.getMessage(), ex);
84 }
85 }
86
87 private static synchronized XPath createXPath() {
88 return xpathFactory.newXPath();
89 }
90
91
92
93 private static class Jaxp13XPathExpression implements XPathExpression {
94
95 private final javax.xml.xpath.XPathExpression xpathExpression;
96
97 private Jaxp13XPathExpression(javax.xml.xpath.XPathExpression xpathExpression) {
98 this.xpathExpression = xpathExpression;
99 }
100
101 public String evaluateAsString(Node node) {
102 return (String) evaluate(node, XPathConstants.STRING);
103 }
104
105 public List<Node> evaluateAsNodeList(Node node) {
106 NodeList nodeList = (NodeList) evaluate(node, XPathConstants.NODESET);
107 return toNodeList(nodeList);
108 }
109
110 private Object evaluate(Node node, QName returnType) {
111 try {
112
113 synchronized (xpathExpression) {
114 return xpathExpression.evaluate(node, returnType);
115 }
116 }
117 catch (XPathExpressionException ex) {
118 throw new XPathException("Could not evaluate XPath expression:" + ex.getMessage(), ex);
119 }
120 }
121
122 private List<Node> toNodeList(NodeList nodeList) {
123 List<Node> result = new ArrayList<Node>(nodeList.getLength());
124 for (int i = 0; i < nodeList.getLength(); i++) {
125 result.add(nodeList.item(i));
126 }
127 return result;
128 }
129
130 public double evaluateAsNumber(Node node) {
131 return (Double) evaluate(node, XPathConstants.NUMBER);
132 }
133
134 public boolean evaluateAsBoolean(Node node) {
135 return (Boolean) evaluate(node, XPathConstants.BOOLEAN);
136 }
137
138 public Node evaluateAsNode(Node node) {
139 return (Node) evaluate(node, XPathConstants.NODE);
140 }
141
142 public <T> T evaluateAsObject(Node node, NodeMapper<T> nodeMapper) throws XPathException {
143 Node result = (Node) evaluate(node, XPathConstants.NODE);
144 if (result != null) {
145 try {
146 return nodeMapper.mapNode(result, 0);
147 }
148 catch (DOMException ex) {
149 throw new XPathException("Mapping resulted in DOMException", ex);
150 }
151 }
152 else {
153 return null;
154 }
155 }
156
157 public <T> List<T> evaluate(Node node, NodeMapper<T> nodeMapper) throws XPathException {
158 NodeList nodes = (NodeList) evaluate(node, XPathConstants.NODESET);
159 List<T> results = new ArrayList<T>(nodes.getLength());
160 for (int i = 0; i < nodes.getLength(); i++) {
161 try {
162 results.add(nodeMapper.mapNode(nodes.item(i), i));
163 }
164 catch (DOMException ex) {
165 throw new XPathException("Mapping resulted in DOMException", ex);
166 }
167 }
168 return results;
169 }
170 }
171
172 }