1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.test.util;
18
19 import java.io.StringReader;
20 import java.util.Collections;
21 import java.util.Map;
22 import javax.xml.namespace.QName;
23 import javax.xml.parsers.DocumentBuilder;
24 import javax.xml.parsers.DocumentBuilderFactory;
25 import javax.xml.xpath.XPath;
26 import javax.xml.xpath.XPathConstants;
27 import javax.xml.xpath.XPathExpression;
28 import javax.xml.xpath.XPathExpressionException;
29 import javax.xml.xpath.XPathFactory;
30
31 import org.hamcrest.Matcher;
32 import org.w3c.dom.Document;
33 import org.w3c.dom.Node;
34 import org.w3c.dom.NodeList;
35 import org.xml.sax.InputSource;
36
37 import org.springframework.util.CollectionUtils;
38 import org.springframework.util.xml.SimpleNamespaceContext;
39
40 import static org.springframework.test.util.AssertionErrors.*;
41 import static org.springframework.test.util.MatcherAssertionErrors.*;
42
43
44
45
46
47
48
49 public class XpathExpectationsHelper {
50
51 private final String expression;
52
53 private final XPathExpression xpathExpression;
54
55 private final boolean hasNamespaces;
56
57
58
59
60
61
62
63
64
65
66
67 public XpathExpectationsHelper(String expression, Map<String, String> namespaces, Object... args)
68 throws XPathExpressionException {
69
70 this.expression = String.format(expression, args);
71 this.xpathExpression = compileXpathExpression(this.expression, namespaces);
72 this.hasNamespaces = !CollectionUtils.isEmpty(namespaces);
73 }
74
75 private XPathExpression compileXpathExpression(String expression, Map<String, String> namespaces)
76 throws XPathExpressionException {
77
78 SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
79 namespaceContext.setBindings((namespaces != null) ? namespaces : Collections.<String, String> emptyMap());
80 XPath xpath = XPathFactory.newInstance().newXPath();
81 xpath.setNamespaceContext(namespaceContext);
82 return xpath.compile(expression);
83 }
84
85
86
87
88 protected XPathExpression getXpathExpression() {
89 return this.xpathExpression;
90 }
91
92
93
94
95
96 public void assertNode(String content, final Matcher<? super Node> matcher) throws Exception {
97 Document document = parseXmlString(content);
98 Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
99 assertThat("XPath " + this.expression, node, matcher);
100 }
101
102
103
104
105
106
107
108
109 protected Document parseXmlString(String xml) throws Exception {
110 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
111 factory.setNamespaceAware(this.hasNamespaces);
112 DocumentBuilder documentBuilder = factory.newDocumentBuilder();
113 InputSource inputSource = new InputSource(new StringReader(xml));
114 Document document = documentBuilder.parse(inputSource);
115 return document;
116 }
117
118
119
120
121
122 @SuppressWarnings("unchecked")
123 protected <T> T evaluateXpath(Document document, QName evaluationType, Class<T> expectedClass)
124 throws XPathExpressionException {
125
126 return (T) getXpathExpression().evaluate(document, evaluationType);
127 }
128
129
130
131
132
133 public void exists(String content) throws Exception {
134 Document document = parseXmlString(content);
135 Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
136 assertTrue("XPath " + this.expression + " does not exist", node != null);
137 }
138
139
140
141
142
143 public void doesNotExist(String content) throws Exception {
144 Document document = parseXmlString(content);
145 Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
146 assertTrue("XPath " + this.expression + " exists", node == null);
147 }
148
149
150
151
152
153
154
155 public void assertNodeCount(String content, Matcher<Integer> matcher) throws Exception {
156 Document document = parseXmlString(content);
157 NodeList nodeList = evaluateXpath(document, XPathConstants.NODESET, NodeList.class);
158 assertThat("nodeCount for XPath " + this.expression, nodeList.getLength(), matcher);
159 }
160
161
162
163
164
165 public void assertNodeCount(String content, int expectedCount) throws Exception {
166 Document document = parseXmlString(content);
167 NodeList nodeList = evaluateXpath(document, XPathConstants.NODESET, NodeList.class);
168 assertEquals("nodeCount for XPath " + this.expression, expectedCount, nodeList.getLength());
169 }
170
171
172
173
174
175
176
177 public void assertString(String content, Matcher<? super String> matcher) throws Exception {
178 Document document = parseXmlString(content);
179 String result = evaluateXpath(document, XPathConstants.STRING, String.class);
180 assertThat("XPath " + this.expression, result, matcher);
181 }
182
183
184
185
186
187 public void assertString(String content, String expectedValue) throws Exception {
188 Document document = parseXmlString(content);
189 String actual = evaluateXpath(document, XPathConstants.STRING, String.class);
190 assertEquals("XPath " + this.expression, expectedValue, actual);
191 }
192
193
194
195
196
197
198
199 public void assertNumber(String content, Matcher<? super Double> matcher) throws Exception {
200 Document document = parseXmlString(content);
201 Double result = evaluateXpath(document, XPathConstants.NUMBER, Double.class);
202 assertThat("XPath " + this.expression, result, matcher);
203 }
204
205
206
207
208
209 public void assertNumber(String content, Double expectedValue) throws Exception {
210 Document document = parseXmlString(content);
211 Double actual = evaluateXpath(document, XPathConstants.NUMBER, Double.class);
212 assertEquals("XPath " + this.expression, expectedValue, actual);
213 }
214
215
216
217
218
219 public void assertBoolean(String content, boolean expectedValue) throws Exception {
220 Document document = parseXmlString(content);
221 String actual = evaluateXpath(document, XPathConstants.STRING, String.class);
222 assertEquals("XPath " + this.expression, expectedValue, Boolean.parseBoolean(actual));
223 }
224
225 }