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