View Javadoc

1   /*
2    * $Id: XPathExtractorTestCase.java 22412 2011-07-14 07:28:59Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
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          // just make code coverage tools happy
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         // just make code coverage tools happy
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         // just make code coverage tools happy
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 }