1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.xml.xpath;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.net.URL;
22  import java.util.List;
23  import javax.xml.parsers.DocumentBuilder;
24  import javax.xml.parsers.DocumentBuilderFactory;
25  import javax.xml.parsers.ParserConfigurationException;
26  import javax.xml.stream.XMLInputFactory;
27  import javax.xml.stream.XMLStreamReader;
28  import javax.xml.transform.Source;
29  import javax.xml.transform.dom.DOMSource;
30  import javax.xml.transform.sax.SAXSource;
31  import javax.xml.transform.stax.StAXSource;
32  import javax.xml.transform.stream.StreamSource;
33  
34  import org.springframework.core.io.ClassPathResource;
35  import org.springframework.xml.sax.SaxUtils;
36  import org.springframework.xml.transform.ResourceSource;
37  
38  import org.junit.Assert;
39  import org.junit.Before;
40  import org.junit.Test;
41  import org.w3c.dom.DOMException;
42  import org.w3c.dom.Document;
43  import org.w3c.dom.Node;
44  import org.xml.sax.InputSource;
45  import org.xml.sax.SAXException;
46  
47  public abstract class AbstractXPathTemplateTestCase {
48  
49      XPathOperations template;
50  
51      private Source namespaces;
52  
53      private Source nonamespaces;
54  
55      @Before
56      public final void setUp() throws Exception {
57          template = createTemplate();
58          namespaces = new ResourceSource(new ClassPathResource("namespaces.xml", AbstractXPathTemplateTestCase.class));
59          nonamespaces =
60                  new ResourceSource(new ClassPathResource("nonamespaces.xml", AbstractXPathTemplateTestCase.class));
61      }
62  
63      protected abstract XPathOperations createTemplate() throws Exception;
64  
65      @Test
66      public void testEvaluateAsBoolean() {
67          boolean result = template.evaluateAsBoolean("/root/child/boolean", nonamespaces);
68          Assert.assertTrue("Invalid result", result);
69      }
70  
71      @Test
72      public void testEvaluateAsBooleanNamespaces() {
73          boolean result = template.evaluateAsBoolean("/prefix1:root/prefix2:child/prefix2:boolean", namespaces);
74          Assert.assertTrue("Invalid result", result);
75      }
76  
77      @Test
78      public void testEvaluateAsDouble() {
79          double result = template.evaluateAsDouble("/root/child/number", nonamespaces);
80          Assert.assertEquals("Invalid result", 42D, result, 0D);
81      }
82  
83      @Test
84      public void testEvaluateAsDoubleNamespaces() {
85          double result = template.evaluateAsDouble("/prefix1:root/prefix2:child/prefix2:number", namespaces);
86          Assert.assertEquals("Invalid result", 42D, result, 0D);
87      }
88  
89      @Test
90      public void testEvaluateAsNode() {
91          Node result = template.evaluateAsNode("/root/child", nonamespaces);
92          Assert.assertNotNull("Invalid result", result);
93          Assert.assertEquals("Invalid localname", "child", result.getLocalName());
94      }
95  
96      @Test
97      public void testEvaluateAsNodeNamespaces() {
98          Node result = template.evaluateAsNode("/prefix1:root/prefix2:child", namespaces);
99          Assert.assertNotNull("Invalid result", result);
100         Assert.assertEquals("Invalid localname", "child", result.getLocalName());
101     }
102 
103     @Test
104     public void testEvaluateAsNodes() {
105         List<Node> results = template.evaluateAsNodeList("/root/child/*", nonamespaces);
106         Assert.assertNotNull("Invalid result", results);
107         Assert.assertEquals("Invalid amount of results", 3, results.size());
108     }
109 
110     @Test
111     public void testEvaluateAsNodesNamespaces() {
112         List<Node> results = template.evaluateAsNodeList("/prefix1:root/prefix2:child/*", namespaces);
113         Assert.assertNotNull("Invalid result", results);
114         Assert.assertEquals("Invalid amount of results", 3, results.size());
115     }
116 
117     @Test
118     public void testEvaluateAsStringNamespaces() throws IOException, SAXException {
119         String result = template.evaluateAsString("/prefix1:root/prefix2:child/prefix2:text", namespaces);
120         Assert.assertEquals("Invalid result", "text", result);
121     }
122 
123     @Test
124     public void testEvaluateAsString() throws IOException, SAXException {
125         String result = template.evaluateAsString("/root/child/text", nonamespaces);
126         Assert.assertEquals("Invalid result", "text", result);
127     }
128 
129     @Test
130     public void testEvaluateDomSource() throws IOException, SAXException, ParserConfigurationException {
131         DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
132         documentBuilderFactory.setNamespaceAware(true);
133         DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
134         Document document = documentBuilder.parse(SaxUtils.createInputSource(
135                 new ClassPathResource("nonamespaces.xml", AbstractXPathTemplateTestCase.class)));
136 
137         String result = template.evaluateAsString("/root/child/text", new DOMSource(document));
138         Assert.assertEquals("Invalid result", "text", result);
139     }
140 
141     @Test
142     public void testEvaluateSAXSource() throws Exception {
143         InputStream in = AbstractXPathTemplateTestCase.class.getResourceAsStream("nonamespaces.xml");
144         SAXSource source = new SAXSource(new InputSource(in));
145         String result = template.evaluateAsString("/root/child/text", source);
146         Assert.assertEquals("Invalid result", "text", result);
147     }
148 
149     @Test
150     public void testEvaluateStaxSource() throws Exception {
151         InputStream in = AbstractXPathTemplateTestCase.class.getResourceAsStream("nonamespaces.xml");
152         XMLStreamReader streamReader = XMLInputFactory.newFactory().createXMLStreamReader(in);
153         StAXSource source = new StAXSource(streamReader);
154         String result = template.evaluateAsString("/root/child/text", source);
155         Assert.assertEquals("Invalid result", "text", result);
156     }
157 
158     @Test
159     public void testEvaluateStreamSourceInputStream() throws IOException, SAXException, ParserConfigurationException {
160         InputStream in = AbstractXPathTemplateTestCase.class.getResourceAsStream("nonamespaces.xml");
161         StreamSource source = new StreamSource(in);
162         String result = template.evaluateAsString("/root/child/text", source);
163         Assert.assertEquals("Invalid result", "text", result);
164     }
165 
166     @Test
167     public void testEvaluateStreamSourceSystemId() throws IOException, SAXException, ParserConfigurationException {
168         URL url = AbstractXPathTemplateTestCase.class.getResource("nonamespaces.xml");
169         String result = template.evaluateAsString("/root/child/text", new StreamSource(url.toString()));
170         Assert.assertEquals("Invalid result", "text", result);
171     }
172 
173     @Test
174     public void testInvalidExpression() {
175         try {
176             template.evaluateAsBoolean("\\", namespaces);
177             Assert.fail("No XPathException thrown");
178         }
179         catch (XPathException ex) {
180             // Expected behaviour
181         }
182     }
183 
184     @Test
185     public void testEvaluateAsObject() throws Exception {
186         String result = template.evaluateAsObject("/root/child", nonamespaces, new NodeMapper<String>() {
187             public String mapNode(Node node, int nodeNum) throws DOMException {
188                 return node.getLocalName();
189             }
190         });
191         Assert.assertNotNull("Invalid result", result);
192         Assert.assertEquals("Invalid localname", "child", result);
193     }
194 
195     @Test
196     public void testEvaluate() throws Exception {
197         List<String> results = template.evaluate("/root/child/*", nonamespaces, new NodeMapper<String>() {
198             public String mapNode(Node node, int nodeNum) throws DOMException {
199                 return node.getLocalName();
200             }
201         });
202         Assert.assertNotNull("Invalid result", results);
203         Assert.assertEquals("Invalid amount of results", 3, results.size());
204         Assert.assertEquals("Invalid first result", "text", results.get(0));
205         Assert.assertEquals("Invalid first result", "number", results.get(1));
206         Assert.assertEquals("Invalid first result", "boolean", results.get(2));
207     }
208 }