1
2
3
4
5
6
7
8
9
10
11 package org.mule.transformers.xml;
12
13 import org.mule.api.config.MuleProperties;
14 import org.mule.api.registry.RegistrationException;
15 import org.mule.api.transformer.TransformerException;
16 import org.mule.module.xml.transformer.XPathExtractor;
17 import org.mule.module.xml.transformer.XPathExtractor.ResultType;
18 import org.mule.module.xml.util.NamespaceManager;
19 import org.mule.tck.junit4.AbstractMuleContextTestCase;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.StringReader;
23 import java.io.StringWriter;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import javax.xml.namespace.NamespaceContext;
28 import javax.xml.parsers.DocumentBuilder;
29 import javax.xml.parsers.DocumentBuilderFactory;
30 import javax.xml.transform.TransformerFactory;
31 import javax.xml.transform.dom.DOMSource;
32 import javax.xml.transform.stream.StreamResult;
33 import javax.xml.xpath.XPath;
34 import javax.xml.xpath.XPathFactory;
35
36 import org.apache.xml.dtm.ref.DTMNodeList;
37 import org.junit.Test;
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Node;
40 import org.xml.sax.InputSource;
41
42 import static org.junit.Assert.assertEquals;
43 import static org.junit.Assert.assertFalse;
44 import static org.junit.Assert.assertNotNull;
45
46 public class XPathExtractorTestCase extends AbstractMuleContextTestCase
47 {
48 protected static final String TEST_XML_MULTI_RESULTS = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
49 + "<root>" + "<node>value1</node>"
50 + "<node>value2</node>" + "<node>value3</node>"
51 + "</root>";
52
53 protected static final String TEST_XML_MULTI_NESTED_RESULTS = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
54 + "<root>"
55 + "<node>"
56 + "<subnode1>val1</subnode1>"
57 + "<subnode2>val2</subnode2>"
58 + "</node>"
59 + "<node>"
60 + "<subnode1>val3</subnode1>"
61 + "<subnode2>val4</subnode2>"
62 + "</node>"
63 + "</root>";
64
65 protected static final String TEST_XML_SINGLE_RESULT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
66 + "<root>" + "<node>value1</node>"
67 + "<node2>2</node2>" + "</root>";
68
69 protected static final String TEST_XML_WITH_NAMESPACES = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root xmlns:f=\"http://www.w3schools.com/furniture\">"
70 + "<f:table>"
71 + "<f:name>African Coffee Table</f:name>"
72 + "<f:width>80</f:width>"
73 + "<f:length>120</f:length>"
74 + "</f:table>"
75 + "</root>";
76
77 @Test(expected=RegistrationException.class)
78 public void expressionIsRequired() throws Exception
79 {
80 createObject(XPathExtractor.class);
81 }
82
83 @Test(expected=TransformerException.class)
84 public void badExpression() throws Exception
85 {
86 final String badExpression = "/$@�%$�&�$$�%";
87 final XPathExtractor extractor = initialiseExtractor(badExpression, ResultType.STRING);
88
89 final Document doc = getDocumentForString(TEST_XML_SINGLE_RESULT);
90 extractor.transform(doc);
91 }
92
93 @Test
94 public void setingXPathEvaluator()
95 {
96 final XPathExtractor extractor = new XPathExtractor();
97 final XPath xPath = XPathFactory.newInstance().newXPath();
98
99
100 extractor.setXpath(xPath);
101 assertEquals("Wrong evaluator returned.", xPath, extractor.getXpath());
102 }
103
104 @Test
105 public void nodeToStringResult() throws Exception
106 {
107 final String expression = "/root/node";
108 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.STRING);
109
110
111 assertEquals("Wrong expression returned.", expression, extractor.getExpression());
112
113 Document doc = getDocumentForString(TEST_XML_SINGLE_RESULT);
114
115 final Object objResult = extractor.transform(doc);
116 assertNotNull(objResult);
117
118 final String result = (String)objResult;
119 assertEquals("Wrong value extracted.", "value1", result);
120 }
121
122 @Test
123 public void inputSourceToStringResult() throws Exception
124 {
125 final String expression = "/root/node";
126 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.STRING);
127
128 final Document doc = getDocumentForString(TEST_XML_SINGLE_RESULT);
129 final InputSource source = getInputSourceForDocument(doc);
130
131 final Object objResult = extractor.transform(source);
132 assertNotNull(objResult);
133
134 final String result = (String)objResult;
135 assertEquals("Wrong value extracted.", "value1", result);
136 }
137
138 @Test
139 public void nodeToNumberResult() throws Exception
140 {
141 final String expression = "/root/node2";
142 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.NUMBER);
143
144 final Document doc = getDocumentForString(TEST_XML_SINGLE_RESULT);
145
146 final Object objResult = extractor.transform(doc);
147 assertNotNull(objResult);
148
149 final double result = ((Double) objResult).doubleValue();
150 assertEquals("Wrong value extracted.", 2.0, result, 0.0);
151 }
152
153 @Test
154 public void nodeToBooleanResult() throws Exception
155 {
156 final String expression = "/root/node2";
157 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.BOOLEAN);
158
159 final Document doc = getDocumentForString(TEST_XML_SINGLE_RESULT);
160
161 final Object objResult = extractor.transform(doc);
162 assertNotNull(objResult);
163
164 final Boolean result = (Boolean)objResult;
165 assertEquals("Wrong value extracted.", Boolean.TRUE, result);
166 }
167
168 @Test
169 public void nodeToNodeResult() throws Exception
170 {
171 final String expression = "/root/node2";
172 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.NODE);
173
174 final Document doc = getDocumentForString(TEST_XML_SINGLE_RESULT);
175
176 final Object objResult = extractor.transform(doc);
177 assertNotNull(objResult);
178
179 final Node result = (Node)objResult;
180 assertEquals("Wrong value extracted.", "node2", result.getNodeName());
181 }
182
183 @Test
184 public void nodeToNodeSetResult() throws Exception
185 {
186 final String expression = "/root/node2";
187 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.NODESET);
188
189 final Document doc = getDocumentForString(TEST_XML_SINGLE_RESULT);
190
191 final Object objResult = extractor.transform(doc);
192 assertNotNull(objResult);
193
194 final DTMNodeList result = (DTMNodeList)objResult;
195 assertEquals("Wrong value extracted.", "node2", result.item(0).getNodeName());
196 }
197
198 @Test
199 public void nodeToStringResultWithNameSpaces() throws Exception
200 {
201 registerNamespaces();
202
203 final String expression = "//f:width";
204 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.STRING);
205
206
207 assertEquals("Wrong expression returned.", expression, extractor.getExpression());
208
209 final Document doc = getDocumentForString(TEST_XML_WITH_NAMESPACES);
210 final Object objResult = extractor.transform(doc);
211 assertNotNull(objResult);
212
213 final String result = (String)objResult;
214 assertEquals("Wrong value extracted.", "80", result);
215 }
216
217 @Test
218 public void xpathNamespacesInitialization() throws Exception
219 {
220 registerNamespaces();
221
222 final String expression = "//f:width";
223 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.STRING);
224
225 final XPath xpath = extractor.getXpath();
226 final NamespaceContext context = xpath.getNamespaceContext();
227 assertEquals("http://www.w3schools.com/furniture", context.getNamespaceURI("f"));
228
229 assertEquals("f", context.getPrefix("http://www.w3schools.com/furniture"));
230 assertEquals(null, context.getPrefix("http://non.existent.name.space"));
231
232 assertEquals("f", context.getPrefixes("http://www.w3schools.com/furniture").next());
233 assertFalse(context.getPrefixes("http://non.existent.name.space").hasNext());
234 }
235
236 @Test
237 public void namespacesNonOverwritten() throws Exception
238 {
239 registerNamespaces();
240
241 final Map<String, String> namespaces = new HashMap<String, String>();
242 namespaces.put("g", "http://www.test.com/g");
243
244 final String expression = "//f:width";
245 final XPathExtractor extractor = initialiseExtractor(expression, ResultType.STRING);
246 extractor.setNamespaces(namespaces);
247
248 assertEquals("http://www.test.com/g", extractor.getNamespaces().get("g"));
249 }
250
251 private void registerNamespaces() throws RegistrationException
252 {
253 final NamespaceManager namespaceManager = new NamespaceManager();
254 final Map<String, String> namespaces = new HashMap<String, String>();
255 namespaces.put("f", "http://www.w3schools.com/furniture");
256 namespaceManager.setNamespaces(namespaces);
257 muleContext.getRegistry().unregisterObject(MuleProperties.OBJECT_MULE_NAMESPACE_MANAGER);
258 muleContext.getRegistry().registerObject(MuleProperties.OBJECT_MULE_NAMESPACE_MANAGER,
259 namespaceManager);
260 }
261
262 private XPathExtractor initialiseExtractor(final String expression, ResultType resultType)
263 throws RegistrationException
264 {
265 final XPathExtractor extractor = new XPathExtractor();
266 extractor.setExpression(expression);
267 extractor.setResultType(resultType);
268 initialiseObject(extractor);
269 return extractor;
270 }
271
272 private Document getDocumentForString(final String xml) throws Exception
273 {
274 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
275
276 factory.setNamespaceAware(true);
277
278 final DocumentBuilder builder = factory.newDocumentBuilder();
279 final Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
280 return doc;
281 }
282
283 private InputSource getInputSourceForDocument(final Document doc) throws Exception
284 {
285 final DOMSource source = new DOMSource(doc);
286 final StringWriter xmlWriter = new StringWriter();
287 final StreamResult xmlResult = new StreamResult(xmlWriter);
288 TransformerFactory.newInstance().newTransformer().transform(source, xmlResult);
289 final StringReader xmlReader = new StringReader(xmlWriter.toString());
290
291 return new InputSource(xmlReader);
292 }
293 }