View Javadoc
1   /*
2    * $Header$
3    * $Revision$
4    * $Date$
5    *
6    * ====================================================================
7    *
8    * Copyright 2000-2003 bob mcwhirter & James Strachan.
9    * All rights reserved.
10   *
11   * Redistribution and use in source and binary forms, with or without
12   * modification, are permitted provided that the following conditions are
13   * met:
14   * 
15   *   * Redistributions of source code must retain the above copyright
16   *     notice, this list of conditions and the following disclaimer.
17   * 
18   *   * Redistributions in binary form must reproduce the above copyright
19   *     notice, this list of conditions and the following disclaimer in the
20   *     documentation and/or other materials provided with the distribution.
21   * 
22   *   * Neither the name of the Jaxen Project nor the names of its
23   *     contributors may be used to endorse or promote products derived 
24   *     from this software without specific prior written permission.
25   * 
26   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
27   * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28   * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
29   * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
30   * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   *
38   * ====================================================================
39   * This software consists of voluntary contributions made by many 
40   * individuals on behalf of the Jaxen Project and was originally 
41   * created by bob mcwhirter <bob@werken.com> and 
42   * James Strachan <jstrachan@apache.org>.  For more information on the 
43   * Jaxen Project, please see <http://www.jaxen.org/>.
44   * 
45   * $Id$
46   */
47  
48  
49  package org.jaxen.test;
50  
51  import junit.framework.TestCase;
52  
53  import javax.xml.parsers.DocumentBuilder;
54  import javax.xml.parsers.DocumentBuilderFactory;
55  import javax.xml.parsers.ParserConfigurationException;
56  
57  import java.io.ByteArrayInputStream;
58  import java.io.IOException;
59  import java.util.Iterator;
60  import java.util.List;
61  
62  import org.jaxen.JaxenException;
63  import org.jaxen.SimpleVariableContext;
64  import org.jaxen.XPath;
65  import org.jaxen.dom.DOMXPath;
66  import org.w3c.dom.Document;
67  import org.w3c.dom.Element;
68  import org.w3c.dom.Node;
69  import org.xml.sax.SAXException;
70  
71  public class DOMXPathTest extends TestCase
72  {
73  
74      private static final String BASIC_XML = "xml/basic.xml";
75      private Document doc;
76      private DocumentBuilderFactory factory;
77  
78      public DOMXPathTest(String name)
79      {
80          super( name );
81      }
82      
83      public void setUp() throws ParserConfigurationException {
84          factory = DocumentBuilderFactory.newInstance();
85          factory.setNamespaceAware(true);
86          doc = factory.newDocumentBuilder().newDocument();        
87      }
88      
89      // Jaxen-221
90      public void  testTimSort() throws ParserConfigurationException, JaxenException {
91          Element root = doc.createElement("root");
92          doc.appendChild(root);
93  
94          // need at least 32 of each to trigger the bug
95          for (int i = 0; i < 32; i++) {
96              root.setAttribute("att" + i, "one");
97          }
98          for (int i = 0; i < 32; i++) {
99              root.appendChild(doc.createElement("child"));
100         }
101 
102         XPath xp = new DOMXPath("//@*[string() = 'one'] | //* ");
103         xp.evaluate(doc);
104     }
105     
106     public void testNamespaceNodesPrecedeAttributeNodes() throws ParserConfigurationException, JaxenException {
107         Element root = doc.createElementNS("http://www.example.org/", "root");
108         doc.appendChild(root);
109         root.setAttribute("att", "one");
110 
111         XPath xp = new DOMXPath("//@* | //namespace::* ");
112         List<?> result = (List<?>) xp.evaluate(doc);
113         assertEquals(3, result.size());
114         Node third = (Node) result.get(2);
115         assertEquals(Node.ATTRIBUTE_NODE, third.getNodeType());
116     }
117     
118     public void testNamespaceNodesPrecedeAttributeNodes2() throws ParserConfigurationException, JaxenException {
119         Element root = doc.createElementNS("http://www.example.org/", "root");
120         doc.appendChild(root);
121         root.setAttribute("att", "one");
122 
123         XPath xp = new DOMXPath("//namespace::* | //@* ");
124         List<?> result = (List<?>) xp.evaluate(doc);
125         assertEquals(3, result.size());
126         Node third = (Node) result.get(2);
127         assertEquals(Node.ATTRIBUTE_NODE, third.getNodeType());
128     }
129     
130     public void testConstruction() throws JaxenException
131     {
132         DOMXPath xpath = new DOMXPath( "/foo/bar/baz" );
133         assertEquals("/foo/bar/baz", xpath.toString());
134     }
135     
136     public void testJaxen193() throws JaxenException
137     {
138         DOMXPath xpath = new DOMXPath( "/*[ * or processing-instruction() ]" );
139         assertEquals("/*[ * or processing-instruction() ]", xpath.toString());
140     }
141     
142     public void testJaxen193InReverse() throws JaxenException
143     {
144         DOMXPath xpath = new DOMXPath( "/*[ processing-instruction() or *]" );
145         assertEquals("/*[ processing-instruction() or *]", xpath.toString());
146     }
147     
148     public void testConstructionWithNamespacePrefix() throws JaxenException
149     {
150         DOMXPath xpath = new DOMXPath( "/p:foo/p:bar/a:baz" );
151         assertEquals("/p:foo/p:bar/a:baz", xpath.toString());
152     }
153     
154     public void testNamespaceDeclarationsAreNotAttributes() 
155       throws JaxenException {
156         
157         Element root = doc.createElementNS("http://www.example.org/", "root");
158         doc.appendChild(root);
159         root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", "http://www.example.org/");
160         
161         DOMXPath xpath = new DOMXPath( "count(/*/@*)" );
162         
163         Number value = xpath.numberValueOf(doc);
164         assertEquals(0, value.intValue());
165         
166     }
167 
168     public void testFunctionWithNamespace() throws IOException, JaxenException {
169         Element root = doc.createElementNS("http://www.example.org/", "root");
170         doc.appendChild(root);
171         XPath xpath = new DOMXPath("//*[not(self::pre:test)]");
172         xpath.addNamespace("pre", "http://www.example.org/");
173         xpath.addNamespace("", "http://www.example.org/");
174         List<?> result = xpath.selectNodes(doc);
175         assertEquals(1, result.size());
176     }
177     
178     public void testVariableWithNamespace() throws IOException, JaxenException {
179         Element root = doc.createElementNS("http://www.example.org/", "root");
180         doc.appendChild(root);
181         XPath xpath = new DOMXPath("//*[not($foo)]");
182         SimpleVariableContext variables = new SimpleVariableContext();
183         variables.setVariableValue("foo", "bar");
184         xpath.setVariableContext(variables);
185         xpath.addNamespace("", "http://www.example.org/");
186         List<?> result = xpath.selectNodes(doc);
187         assertEquals(0, result.size());
188     }
189 
190     public void testElementWithoutNamespace() throws IOException, JaxenException {
191         Element root = doc.createElement("root");
192         doc.appendChild(root);
193         XPath xpath = new DOMXPath("//root");
194         xpath.addNamespace("", "http://www.example.org/");
195         List<?> result = xpath.selectNodes(doc);
196         assertEquals(1, result.size());
197     }
198 
199     // see JAXEN-214
200     public void testAttributeNodesDontHaveChildren() 
201       throws JaxenException {
202         
203         Element root = doc.createElement("root");
204         doc.appendChild(root);
205         root.setAttribute("name", "value");
206         
207         XPath xpath = new DOMXPath("//@*/text()");
208         List<?> result = xpath.selectNodes(doc);
209         assertEquals(0, result.size());
210     }
211     
212     // see JAXEN-105
213     public void testConsistentNamespaceDeclarations() 
214       throws JaxenException {
215         
216         Element root = doc.createElement("root");
217         doc.appendChild(root);
218         Element child = doc.createElementNS("http://www.example.org", "foo:child");
219         root.appendChild(child);
220         // different prefix
221         child.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:foo2", "http://www.contradictory.org");
222         
223         XPath xpath = new DOMXPath("//namespace::node()");
224         List<?> result = xpath.selectNodes(doc);
225         assertEquals(4, result.size());
226         
227     }
228 
229     // see JAXEN-105
230     public void testInconsistentNamespaceDeclarations() 
231       throws JaxenException {
232         
233         Element root = doc.createElement("root");
234         doc.appendChild(root);
235         Element child = doc.createElementNS("http://www.example.org", "foo:child");
236         root.appendChild(child);
237         // same prefix
238         child.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:foo", "http://www.contradictory.org");
239         
240         XPath xpath = new DOMXPath("//namespace::node()");
241         List<?> result = xpath.selectNodes(doc);
242         assertEquals(3, result.size());
243         
244     }
245 
246     // see JAXEN-105
247     public void testIntrinsicNamespaceDeclarationOfElementBeatsContradictoryXmlnsPreAttr() 
248       throws JaxenException {
249         
250         Element root = doc.createElement("root");
251         doc.appendChild(root);
252         Element child = doc.createElementNS("http://www.example.org", "foo:child");
253         root.appendChild(child);
254         // same prefix
255         child.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:foo", "http://www.contradictory.org");
256         
257         XPath xpath = new DOMXPath("//namespace::node()[name(.)='foo']");
258         List<?> result = xpath.selectNodes(doc);
259         assertEquals(1, result.size());
260         Node node = (Node) result.get(0);
261         assertEquals("http://www.example.org", node.getNodeValue());
262         
263     }    
264     
265     // see JAXEN-105
266     public void testIntrinsicNamespaceDeclarationOfAttrBeatsContradictoryXmlnsPreAttr() 
267       throws JaxenException {
268         
269         Element root = doc.createElement("root");
270         doc.appendChild(root);
271         root.setAttributeNS("http://www.example.org/", "foo:a", "value");
272         // same prefix, different namespace
273         root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:foo", "http://www.contradictory.org");
274         
275         XPath xpath = new DOMXPath("//namespace::node()[name(.)='foo']");
276         List<?> result = xpath.selectNodes(doc);
277         assertEquals(1, result.size());
278         Node node = (Node) result.get(0);
279         assertEquals("http://www.example.org/", node.getNodeValue());
280         
281     }    
282     
283     // see JAXEN-105
284     public void testIntrinsicNamespaceDeclarationOfElementBeatsContradictoryIntrinsicNamespaceOfAttr() 
285       throws JaxenException {
286         
287         Element root = doc.createElementNS("http://www.example.org", "pre:root");
288         doc.appendChild(root);
289         // same prefix
290         root.setAttributeNS("http://www.contradictory.org", "pre:foo", "value");
291         
292         XPath xpath = new DOMXPath("//namespace::node()[name(.)='pre']");
293         List<?> result = xpath.selectNodes(doc);
294         assertEquals(1, result.size());
295         Node node = (Node) result.get(0);
296         assertEquals("http://www.example.org", node.getNodeValue());
297         
298     }    
299     
300     // Jaxen-54
301     public void testUpdateDOMNodesReturnedBySelectNodes() 
302       throws JaxenException {
303         
304         Element root = doc.createElementNS("http://www.example.org/", "root");
305         doc.appendChild(root);
306         root.appendChild(doc.createComment("data"));
307         
308         DOMXPath xpath = new DOMXPath( "//comment()" );
309         
310         List<?> results = xpath.selectNodes(doc);
311         Node backroot = (Node) results.get(0);
312         backroot.setNodeValue("test");
313         assertEquals("test", backroot.getNodeValue());
314         
315     }
316 
317     public void testSelection() 
318       throws JaxenException, ParserConfigurationException, SAXException, IOException {
319         XPath xpath = new DOMXPath( "/foo/bar/baz" );
320 
321         DocumentBuilder builder = factory.newDocumentBuilder();
322     
323         Document document = builder.parse( BASIC_XML );
324 
325         List<?> results = xpath.selectNodes( document );
326 
327         assertEquals( 3,
328                       results.size() );
329 
330         Iterator<?> iter = results.iterator();
331 
332         assertEquals( "baz",
333                       ((Element)iter.next()).getLocalName() );
334 
335         assertEquals( "baz",
336                       ((Element)iter.next()).getLocalName() );
337 
338         assertEquals( "baz",
339                       ((Element)iter.next()).getLocalName() );
340 
341         assertTrue( ! iter.hasNext() );
342 
343     }
344     
345     // Jaxen-22
346     public void testPrecedingAxisWithPositionalPredicate() 
347       throws JaxenException, ParserConfigurationException, SAXException, IOException {
348         
349         XPath xpath = new DOMXPath( "//c/preceding::*[1][name()='d']" );
350         DocumentBuilder builder = factory.newDocumentBuilder();
351     
352         Document document = builder.parse( "xml/web2.xml" );
353         List<?> result = xpath.selectNodes(document);
354         assertEquals(1, result.size());
355         
356     }
357     
358      
359     // Jaxen-22
360     public void testJaxen22() 
361       throws JaxenException, ParserConfigurationException, SAXException, IOException {
362         
363         XPath xpath = new DOMXPath( "name(//c/preceding::*[1])" );
364         DocumentBuilder builder = factory.newDocumentBuilder();
365     
366         doc = builder.parse("xml/web2.xml");
367         Object result = xpath.evaluate(doc);
368         assertEquals("d", result);
369     }
370     
371 
372     public void testJaxen207() 
373       throws JaxenException {
374         new DOMXPath( "contains($FinResp, \"NS_Payables_Associate\") or"
375                 + "contains($FinResp, \"NS_Payables_Manager\") or"
376                 + "contains($FinResp, \"NS_Payment_Processing\") or"
377                 + "contains($FinResp, \"NS_Vendor_Maintenance\") or"
378                 + "contains($FinResp, \"NS_IB_Receivables_Manager\") or"
379                 + "contains($FinResp, \"NS_IB_Receivables_User\") or"
380                 + "contains($FinResp, \"NS_Receivables_Manager\") or"
381                 + "contains($FinResp, \"NS_Receivables_User\") or"
382                 + "contains($FinResp, \"NS_Cash_Management_User\") or"
383                 + "contains($FinResp, \"NS_Cost_Management\") or"
384                 + "contains($FinResp, \"NS_Fixed_Assets_Manager\") or"
385                 + "contains($FinResp, \"NS_Fixed_Asset_User\") or"
386                 + "contains($FinResp, \"NS_General_Ledger_Inquiry\") or"
387                 + "contains($FinResp, \"NS_General_Ledger_User\") or"
388                 + "contains($FinResp, \"NS_General_Ledger_Supervisor\") or"
389                 + "contains($FinResp, \"NS_IB_General_Ledger_User\") or"
390                 + "contains($FinResp, \"NS_IB_Oracle_Web_ADI\") or"
391                 + "contains($FinResp, \"NS_Oracle_Web_ADI\") or"
392          + "contains($FinResp, \"NS_CRM_Resource_Manager\") or"
393                 + "contains($FinResp, \"NS_Distributor_Manager\") or"
394                 + "contains($FinResp, \"NS_OIC_User\") or"
395                 + "contains($FinResp, \" NS_Operations_Buyer\") or"
396                 + "contains($FinResp, \"NS_Purchasing_Buyer\") or"
397                 + "contains($FinResp, \"NS_Vendor_Maintenance\") or "
398               + "contains($FinResp, \"SL_Payables_Manager\") or"
399                 + "contains($FinResp, \"SL_Payables_Super_User\") or"
400                 + "contains($FinResp, \"SL_Payment_Processing\") or"
401                 + "contains($FinResp, \"SL_Vendor_Maintenance\") or"
402                 + "contains($InvResp, \"SL_Inventory_Super_User\") or"
403                          + "contains($FinResp, \"\") or"
404                 + "contains($FinResp, \"SL_Receivables_Supervisor\") or"
405                 + "contains($FinResp, \"SL_Receivables_User\") or"
406                 + "contains($FinResp, \"NS_Cost_Management_Inquiry\") or"
407                 + "contains($FinResp, \"SL_Fixed_Asset_User\") or"
408                 + "contains($FinResp, \"SL_Fixed_Assets_Manager\") or"
409                 + "contains($FinResp, \"SL_General_Ledger_Inquiry\") or"
410                 + "contains($FinResp, \"SL_General_Ledger_Supervisor\") or"
411                 + "contains($FinResp, \"SL_General_Ledger_User\") or"
412                 + "contains($FinResp, \"SL_Oracle_Web_ADI\") or"
413                 + "contains($FinResp, \"SL_Buyer\") or"
414                 + "contains($FinResp, \"SL_Purchasing_Inquiry\") or"
415                 + "contains($FinResp, \"SL_Payables_Manager\") or"
416                 + "contains($FinResp, \"SL_Payables_Super_User\") or"
417                 + "contains($FinResp, \"SL_Payment_Processing\") or"
418                 + "contains($FinResp, \"SL_Vendor_Maintenance\") or"
419                 + "contains($InvResp, \"SL_Inventory_Super_User\") or"
420                 + "contains($FinResp, \"\") or"
421                 + "contains($FinResp, \"SL_Receivables_Supervisor\") or"
422                 + "contains($FinResp, \"SL_Receivables_User\") or"
423                 + "contains($FinResp, \"NS_Cost_Management_Inquiry\") or"
424                 + "contains($FinResp, \"SL_Fixed_Asset_User\") or"
425                 + "contains($FinResp, \"SL_Fixed_Assets_Manager\") or"
426                 + "contains($FinResp, \"SL_General_Ledger_Inquiry\") or"
427                 + "contains($FinResp, \"SL_General_Ledger_Supervisor\") or"
428                 + "contains($FinResp, \"SL_General_Ledger_User\") or"
429                 + "contains($FinResp, \"SL_Oracle_Web_ADI\") or"
430                 + "contains($FinResp, \"SL_Buyer\") or"
431                 + "contains($FinResp, \"SL_Purchasing_Inquiry\")");
432     }
433 
434 
435     public void testImplictCastFromTextInARelationalExpression() 
436       throws JaxenException, ParserConfigurationException, SAXException, IOException {
437         XPath implicitCast = new DOMXPath("//lat[(text() >= 37)]");
438         XPath explicitCast = new DOMXPath("//lat[(number(text()) >= 37)]");
439         DocumentBuilder builder = factory.newDocumentBuilder();
440         ByteArrayInputStream in = new ByteArrayInputStream("<geo><lat>39</lat></geo>".getBytes("UTF-8"));
441         Document document = builder.parse(in);
442         List<?> explicitResult = explicitCast.selectNodes(document);
443         assertEquals(1, explicitResult.size());
444         List<?> implicitResult = implicitCast.selectNodes(document);
445         assertEquals(1, implicitResult.size());
446     }
447     
448      
449     public void testImplictCastFromCommentInARelationalExpression() 
450       throws JaxenException, ParserConfigurationException, SAXException, IOException {
451           XPath implicitCast = new DOMXPath("//lat[(comment() >= 37)]");
452           XPath explicitCast = new DOMXPath("//lat[(number(comment()) >= 37)]");
453           DocumentBuilder builder = factory.newDocumentBuilder();
454           ByteArrayInputStream in = new ByteArrayInputStream("<geo><lat><!--39--></lat></geo>".getBytes("UTF-8"));
455           Document document = builder.parse(in);
456           List<?> explicitResult = explicitCast.selectNodes(document);
457           assertEquals(1, explicitResult.size());
458           List<?> implicitResult = implicitCast.selectNodes(document);
459           assertEquals(1, implicitResult.size());
460     }
461   
462 
463     public void testImplictCastFromProcessingInstructionInARelationalExpression() 
464       throws JaxenException, ParserConfigurationException, SAXException, IOException {
465         XPath implicitCast = new DOMXPath("//lat[(processing-instruction() >= 37)]");
466         XPath explicitCast = new DOMXPath("//lat[(number(processing-instruction()) >= 37)]");
467         DocumentBuilder builder = factory.newDocumentBuilder();
468         ByteArrayInputStream in = new ByteArrayInputStream("<geo><lat><?test 39?></lat></geo>".getBytes("UTF-8"));
469         Document document = builder.parse(in);
470         List<?> explicitResult = explicitCast.selectNodes(document);
471         assertEquals(1, explicitResult.size());
472         List<?> implicitResult = implicitCast.selectNodes(document);
473         assertEquals(1, implicitResult.size());
474     }
475     
476     public void testPrecedingAxisInDocumentOrder() 
477       throws JaxenException {
478         
479         XPath xpath = new DOMXPath( "preceding::*" );
480     
481         Element root = doc.createElement("root");
482         doc.appendChild(root);
483         
484         Element a = doc.createElement("a");
485         root.appendChild(a);
486         Element b = doc.createElement("b");
487         root.appendChild(b);
488         Element c = doc.createElement("c");
489         a.appendChild(c);
490         
491         List<?> result = xpath.selectNodes(b);
492         assertEquals(2, result.size());
493         assertEquals(a, result.get(0));
494         assertEquals(c, result.get(1));
495     }
496     
497      
498 }