1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.parsing;
17
18 import java.io.InputStream;
19 import java.io.Reader;
20 import java.io.StringReader;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Properties;
24
25 import javax.xml.namespace.QName;
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.xpath.XPath;
29 import javax.xml.xpath.XPathConstants;
30 import javax.xml.xpath.XPathFactory;
31
32 import org.apache.ibatis.builder.BuilderException;
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Node;
35 import org.w3c.dom.NodeList;
36 import org.xml.sax.EntityResolver;
37 import org.xml.sax.ErrorHandler;
38 import org.xml.sax.InputSource;
39 import org.xml.sax.SAXException;
40 import org.xml.sax.SAXParseException;
41
42
43
44
45 public class XPathParser {
46
47 private Document document;
48 private boolean validation;
49 private EntityResolver entityResolver;
50 private Properties variables;
51 private XPath xpath;
52
53 public XPathParser(String xml) {
54 commonConstructor(false, null, null);
55 this.document = createDocument(new InputSource(new StringReader(xml)));
56 }
57
58 public XPathParser(Reader reader) {
59 commonConstructor(false, null, null);
60 this.document = createDocument(new InputSource(reader));
61 }
62
63 public XPathParser(InputStream inputStream) {
64 commonConstructor(false, null, null);
65 this.document = createDocument(new InputSource(inputStream));
66 }
67
68 public XPathParser(Document document) {
69 commonConstructor(false, null, null);
70 this.document = document;
71 }
72
73 public XPathParser(String xml, boolean validation) {
74 commonConstructor(validation, null, null);
75 this.document = createDocument(new InputSource(new StringReader(xml)));
76 }
77
78 public XPathParser(Reader reader, boolean validation) {
79 commonConstructor(validation, null, null);
80 this.document = createDocument(new InputSource(reader));
81 }
82
83 public XPathParser(InputStream inputStream, boolean validation) {
84 commonConstructor(validation, null, null);
85 this.document = createDocument(new InputSource(inputStream));
86 }
87
88 public XPathParser(Document document, boolean validation) {
89 commonConstructor(validation, null, null);
90 this.document = document;
91 }
92
93 public XPathParser(String xml, boolean validation, Properties variables) {
94 commonConstructor(validation, variables, null);
95 this.document = createDocument(new InputSource(new StringReader(xml)));
96 }
97
98 public XPathParser(Reader reader, boolean validation, Properties variables) {
99 commonConstructor(validation, variables, null);
100 this.document = createDocument(new InputSource(reader));
101 }
102
103 public XPathParser(InputStream inputStream, boolean validation, Properties variables) {
104 commonConstructor(validation, variables, null);
105 this.document = createDocument(new InputSource(inputStream));
106 }
107
108 public XPathParser(Document document, boolean validation, Properties variables) {
109 commonConstructor(validation, variables, null);
110 this.document = document;
111 }
112
113 public XPathParser(String xml, boolean validation, Properties variables, EntityResolver entityResolver) {
114 commonConstructor(validation, variables, entityResolver);
115 this.document = createDocument(new InputSource(new StringReader(xml)));
116 }
117
118 public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) {
119 commonConstructor(validation, variables, entityResolver);
120 this.document = createDocument(new InputSource(reader));
121 }
122
123 public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
124 commonConstructor(validation, variables, entityResolver);
125 this.document = createDocument(new InputSource(inputStream));
126 }
127
128 public XPathParser(Document document, boolean validation, Properties variables, EntityResolver entityResolver) {
129 commonConstructor(validation, variables, entityResolver);
130 this.document = document;
131 }
132
133 public void setVariables(Properties variables) {
134 this.variables = variables;
135 }
136
137 public String evalString(String expression) {
138 return evalString(document, expression);
139 }
140
141 public String evalString(Object root, String expression) {
142 String result = (String) evaluate(expression, root, XPathConstants.STRING);
143 result = PropertyParser.parse(result, variables);
144 return result;
145 }
146
147 public Boolean evalBoolean(String expression) {
148 return evalBoolean(document, expression);
149 }
150
151 public Boolean evalBoolean(Object root, String expression) {
152 return (Boolean) evaluate(expression, root, XPathConstants.BOOLEAN);
153 }
154
155 public Short evalShort(String expression) {
156 return evalShort(document, expression);
157 }
158
159 public Short evalShort(Object root, String expression) {
160 return Short.valueOf(evalString(root, expression));
161 }
162
163 public Integer evalInteger(String expression) {
164 return evalInteger(document, expression);
165 }
166
167 public Integer evalInteger(Object root, String expression) {
168 return Integer.valueOf(evalString(root, expression));
169 }
170
171 public Long evalLong(String expression) {
172 return evalLong(document, expression);
173 }
174
175 public Long evalLong(Object root, String expression) {
176 return Long.valueOf(evalString(root, expression));
177 }
178
179 public Float evalFloat(String expression) {
180 return evalFloat(document, expression);
181 }
182
183 public Float evalFloat(Object root, String expression) {
184 return Float.valueOf(evalString(root, expression));
185 }
186
187 public Double evalDouble(String expression) {
188 return evalDouble(document, expression);
189 }
190
191 public Double evalDouble(Object root, String expression) {
192 return (Double) evaluate(expression, root, XPathConstants.NUMBER);
193 }
194
195 public List<XNode> evalNodes(String expression) {
196 return evalNodes(document, expression);
197 }
198
199 public List<XNode> evalNodes(Object root, String expression) {
200 List<XNode> xnodes = new ArrayList<XNode>();
201 NodeList nodes = (NodeList) evaluate(expression, root, XPathConstants.NODESET);
202 for (int i = 0; i < nodes.getLength(); i++) {
203 xnodes.add(new XNode(this, nodes.item(i), variables));
204 }
205 return xnodes;
206 }
207
208 public XNode evalNode(String expression) {
209 return evalNode(document, expression);
210 }
211
212 public XNode evalNode(Object root, String expression) {
213 Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
214 if (node == null) {
215 return null;
216 }
217 return new XNode(this, node, variables);
218 }
219
220 private Object evaluate(String expression, Object root, QName returnType) {
221 try {
222 return xpath.evaluate(expression, root, returnType);
223 } catch (Exception e) {
224 throw new BuilderException("Error evaluating XPath. Cause: " + e, e);
225 }
226 }
227
228 private Document createDocument(InputSource inputSource) {
229
230 try {
231 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
232 factory.setValidating(validation);
233
234 factory.setNamespaceAware(false);
235 factory.setIgnoringComments(true);
236 factory.setIgnoringElementContentWhitespace(false);
237 factory.setCoalescing(false);
238 factory.setExpandEntityReferences(true);
239
240 DocumentBuilder builder = factory.newDocumentBuilder();
241 builder.setEntityResolver(entityResolver);
242 builder.setErrorHandler(new ErrorHandler() {
243 @Override
244 public void error(SAXParseException exception) throws SAXException {
245 throw exception;
246 }
247
248 @Override
249 public void fatalError(SAXParseException exception) throws SAXException {
250 throw exception;
251 }
252
253 @Override
254 public void warning(SAXParseException exception) throws SAXException {
255 }
256 });
257 return builder.parse(inputSource);
258 } catch (Exception e) {
259 throw new BuilderException("Error creating document instance. Cause: " + e, e);
260 }
261 }
262
263 private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
264 this.validation = validation;
265 this.entityResolver = entityResolver;
266 this.variables = variables;
267 XPathFactory factory = XPathFactory.newInstance();
268 this.xpath = factory.newXPath();
269 }
270
271 }