1   /*
2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3    *
4    * This software is open source.
5    * See the bottom of this file for the licence.
6    */
7   
8   package org.dom4j;
9   
10  import junit.textui.TestRunner;
11  
12  import java.io.StringReader;
13  import java.util.Iterator;
14  import java.util.List;
15  
16  import javax.xml.parsers.DocumentBuilder;
17  import javax.xml.parsers.DocumentBuilderFactory;
18  
19  import org.dom4j.io.DOMReader;
20  
21  import org.xml.sax.InputSource;
22  
23  /***
24   * Test the use of namespaces
25   * 
26   * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
27   * @version $Revision: 1.4 $
28   */
29  public class NamespacesTest extends AbstractTestCase {
30      public static void main(String[] args) {
31          TestRunner.run(NamespacesTest.class);
32      }
33  
34      // Test case(s)
35      // -------------------------------------------------------------------------
36      public void testNamespaces() throws Exception {
37          testNamespaces(document);
38          testNamespaces(saxRoundTrip(document));
39          testNamespaces(domRoundTrip(document));
40      }
41  
42      public void testNamespaces(Document document) throws Exception {
43          Document doc2 = (Document) document.clone();
44  
45          Element root = doc2.getRootElement();
46          assertNamespace(root.getNamespace(), "",
47                  "http://www.w3.org/2001/XMLSchema");
48          assertEquals("xmlns=\"http://www.w3.org/2001/XMLSchema\"", root
49                  .getNamespace().asXML());
50          assertEquals("namespace::*[name()='']", root.getNamespace().getPath());
51          assertEquals("namespace::*[name()='']", root.getNamespace()
52                  .getUniquePath());
53  
54          List additionalNS = root.additionalNamespaces();
55          assertTrue("at least one additional namespace", (additionalNS != null)
56                  && (additionalNS.size() > 0));
57  
58          Namespace ns = (Namespace) additionalNS.get(0);
59          assertNamespace(ns, "t", "http://www.w3.org/namespace/");
60          assertEquals("xmlns:t=\"http://www.w3.org/namespace/\"", ns.asXML());
61          assertEquals("namespace::t", ns.getPath());
62          assertEquals("namespace::t", ns.getUniquePath());
63  
64          Node node = root.node(0);
65          assertTrue("First node is a namespace", node instanceof Namespace);
66  
67          // now lets try change the namespace
68          root.remove(ns);
69          root.addNamespace("t", "myNewURI");
70  
71          additionalNS = root.additionalNamespaces();
72          assertTrue("at least one additional namespace", (additionalNS != null)
73                  && (additionalNS.size() > 0));
74  
75          ns = (Namespace) additionalNS.get(0);
76          assertNamespace(ns, "t", "myNewURI");
77  
78          // lets test the list is backed
79          additionalNS.remove(0);
80          additionalNS.add(Namespace.get("t", "myNewURI-2"));
81  
82          additionalNS = root.additionalNamespaces();
83          assertTrue("at least one additional namespace", (additionalNS != null)
84                  && (additionalNS.size() > 0));
85  
86          ns = (Namespace) additionalNS.get(0);
87          assertNamespace(ns, "t", "myNewURI-2");
88  
89          additionalNS.clear();
90          root.addNamespace("t", "myNewURI");
91  
92          additionalNS = root.additionalNamespaces();
93          assertTrue("at least one additional namespace", (additionalNS != null)
94                  && (additionalNS.size() > 0));
95  
96          ns = (Namespace) additionalNS.get(0);
97          assertNamespace(ns, "t", "myNewURI");
98  
99          log("Namespaces: " + additionalNS);
100         log("XML is now");
101         log(root.asXML());
102     }
103 
104     public void testNamespaceForPrefix() throws Exception {
105         testNamespaceForPrefix(document);
106         testNamespaceForPrefix(saxRoundTrip(document));
107         testNamespaceForPrefix(domRoundTrip(document));
108     }
109 
110     public void testNamespaceForPrefix(Document document) throws Exception {
111         Element root = document.getRootElement();
112         Namespace ns = root.getNamespaceForPrefix("t");
113 
114         assertNamespace(ns, "t", "http://www.w3.org/namespace/");
115 
116         Element element = (Element) root.elements().get(0);
117         Namespace ns2 = element.getNamespaceForPrefix("t");
118 
119         assertNamespace(ns2, "t", "http://www.w3.org/namespace/");
120         assertTrue("Same namespace instance returned", ns == ns2);
121 
122         log("found: " + ns.asXML());
123     }
124 
125     public void testNamespaceForDefaultPrefix() throws Exception {
126         Document document = getDocument("/xml/test/defaultNamespace.xml");
127 
128         testNamespaceForDefaultPrefix(document);
129         testNamespaceForDefaultPrefix(saxRoundTrip(document));
130         testNamespaceForDefaultPrefix(domRoundTrip(document));
131     }
132 
133     public void testNamespaceForDefaultPrefix(Document document)
134             throws Exception {
135         List list = document.selectNodes("//*");
136 
137         for (Iterator iter = list.iterator(); iter.hasNext();) {
138             Element element = (Element) iter.next();
139             Namespace ns = element.getNamespaceForPrefix("");
140             assertNamespace(ns, "", "dummyNamespace");
141             ns = element.getNamespaceForPrefix(null);
142             assertNamespace(ns, "", "dummyNamespace");
143             log("found: " + ns.asXML());
144         }
145     }
146 
147     public void testAttributeDefaultPrefix() throws Exception {
148         Document document = getDocument("/xml/test/soap3.xml");
149 
150         testAttributeDefaultPrefix(document);
151         testAttributeDefaultPrefix(saxRoundTrip(document));
152         testAttributeDefaultPrefix(domRoundTrip(document));
153     }
154 
155     public void testAttributeDefaultPrefix(Document document) throws Exception {
156         List list = document.selectNodes("//@*[local-name()='actor']");
157 
158         assertTrue("Matched at least one 'actor' attribute", list.size() > 0);
159 
160         for (Iterator iter = list.iterator(); iter.hasNext();) {
161             Attribute attribute = (Attribute) iter.next();
162 
163             log("found: " + attribute.asXML());
164 
165             Element element = attribute.getParent();
166             assertTrue("Attribute has a parent", element != null);
167 
168             Namespace ns = element.getNamespaceForPrefix("");
169 
170             String uri = "http://schemas.xmlsoap.org/soap/envelope/";
171             assertNamespace(ns, "", uri);
172 
173             Namespace ns2 = attribute.getNamespace();
174 
175             // Note that namespaces do not inherit the default namespace!
176             assertNamespace(ns2, "", "");
177         }
178     }
179 
180     public void testNamespaceForURI() throws Exception {
181         testNamespaceForURI(document);
182         testNamespaceForURI(saxRoundTrip(document));
183         testNamespaceForURI(domRoundTrip(document));
184     }
185 
186     public void testNamespaceForURI(Document document) throws Exception {
187         Element root = document.getRootElement();
188 
189         Namespace ns = root.getNamespaceForURI("http://www.w3.org/namespace/");
190 
191         assertNamespace(ns, "t", "http://www.w3.org/namespace/");
192 
193         Element element = (Element) root.elements().get(0);
194         Namespace ns2 = element
195                 .getNamespaceForURI("http://www.w3.org/namespace/");
196 
197         assertNamespace(ns2, "t", "http://www.w3.org/namespace/");
198 
199         assertTrue("Same namespace instance returned", ns == ns2);
200 
201         log("found: " + ns.asXML());
202     }
203 
204     public void testRedeclareNamespaces() throws Exception {
205         Document document = getDocument("/xml/test/soap2.xml");
206         testRedeclareNamespaces(document);
207         testRedeclareNamespaces(saxRoundTrip(document));
208         testRedeclareNamespaces(domRoundTrip(document));
209     }
210 
211     public void testRedeclareNamespaces(Document document) throws Exception {
212         String uri = "http://schemas.xmlsoap.org/soap/envelope/";
213         assertNamespaces(document.selectNodes("//*[local-name()='Envelope']"),
214                 "SOAP-ENV", uri);
215         assertNamespaces(document.selectNodes("//*[local-name()='Body']"),
216                 "SOAP-ENV", uri);
217         assertNamespaces(document.selectNodes("//*[local-name()='bar']"), "a",
218                 "barURI");
219         assertNamespaces(document.selectNodes("//*[local-name()='newBar']"),
220                 "a", "newBarURI");
221         assertNamespaces(document.selectNodes("//*[local-name()='foo']"), "",
222                 "fooURI");
223         assertNamespaces(document.selectNodes("//*[local-name()='newFoo']"),
224                 "", "newFooURI");
225     }
226 
227     public void testDefaultNamespaceIssue() throws Exception {
228         Document document = getDocument("/xml/test/defaultNamespaceIssue.xsd");
229         testDefaultNamespaceIssue(document);
230         testDefaultNamespaceIssue(saxRoundTrip(document));
231         testDefaultNamespaceIssue(domRoundTrip(document));
232     }
233 
234     public void testDefaultNamespaceIssue(Document document) throws Exception {
235         // When writing documents using a default namespace with XMLWriter
236         // a redeclaration of the default namespace to "" was dropped in the
237         // output. Test that
238         // <xsd:schema><xsd:element><xsd:annotation><xsd:documentation><text>
239         // is in no namespace.
240         String expr 
241             = "/xsd:schema/xsd:element/xsd:annotation/xsd:documentation/text";
242         assertNotNull("default namespace redeclaration", (Element) document
243                 .selectSingleNode(expr));
244 
245         // The test document has a default namespace declaration on the root
246         // element ("schema"), but the element itself is not in the default
247         // namespace. Test that declaredNamespaces on the root element also
248         // returns the default namespace declaration.
249         Iterator iter = document.getRootElement().declaredNamespaces()
250                 .iterator();
251 
252         while (iter.hasNext()) {
253             Namespace ns = (Namespace) iter.next();
254 
255             if ("urn:wapforum:devicesheet".equals(ns.getURI())
256                     && "".equals(ns.getPrefix())) {
257                 return;
258             }
259         }
260 
261         fail("Default namespace declaration not present on root element");
262     }
263 
264     public void testDefaultNamespace() throws Exception {
265         Document doc = DocumentHelper.createDocument();
266         Element processDef = doc.addElement("process-definition",
267                 "http://jbpm.org/statedefinition-2.0-beta3");
268         Element startState = processDef.addElement("start-state");
269         startState.addAttribute("name", "start");
270 
271         Element transition = startState.addElement("transition");
272         transition.addAttribute("to", "first");
273 
274         assertEquals("http://jbpm.org/statedefinition-2.0-beta3", startState
275                 .getNamespace().getURI());
276         assertEquals("", startState.getNamespace().getPrefix());
277 
278         System.out.println(doc.asXML());
279     }
280 
281     // Implementation methods
282     // -------------------------------------------------------------------------
283     protected void setUp() throws Exception {
284         super.setUp();
285         document = getDocument("/xml/test/test_schema.xml");
286     }
287 
288     protected Document saxRoundTrip(Document document) throws Exception {
289         return DocumentHelper.parseText(document.asXML());
290     }
291 
292     protected Document domRoundTrip(Document document) throws Exception {
293         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
294         factory.setNamespaceAware(true);
295 
296         DocumentBuilder builder = factory.newDocumentBuilder();
297         org.w3c.dom.Document domDocument = builder.parse(new InputSource(
298                 new StringReader(document.asXML())));
299 
300         // now lets read it back as a DOM4J object
301         DOMReader domReader = new DOMReader();
302 
303         return domReader.read(domDocument);
304     }
305 
306     protected void assertNamespaces(List elements, String prefix, String uri)
307             throws Exception {
308         for (Iterator iter = elements.iterator(); iter.hasNext();) {
309             Element element = (Element) iter.next();
310             assertNamespace(element.getNamespace(), prefix, uri);
311         }
312     }
313 
314     protected void assertNamespace(Namespace ns, String prefix, String uri)
315             throws Exception {
316         assertEquals("namespace prefix", prefix, ns.getPrefix());
317         assertEquals("namespace URI", uri, ns.getURI());
318     }
319 }
320 
321 /*
322  * Redistribution and use of this software and associated documentation
323  * ("Software"), with or without modification, are permitted provided that the
324  * following conditions are met:
325  * 
326  * 1. Redistributions of source code must retain copyright statements and
327  * notices. Redistributions must also contain a copy of this document.
328  * 
329  * 2. Redistributions in binary form must reproduce the above copyright notice,
330  * this list of conditions and the following disclaimer in the documentation
331  * and/or other materials provided with the distribution.
332  * 
333  * 3. The name "DOM4J" must not be used to endorse or promote products derived
334  * from this Software without prior written permission of MetaStuff, Ltd. For
335  * written permission, please contact dom4j-info@metastuff.com.
336  * 
337  * 4. Products derived from this Software may not be called "DOM4J" nor may
338  * "DOM4J" appear in their names without prior written permission of MetaStuff,
339  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
340  * 
341  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
342  * 
343  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
344  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
345  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
346  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
347  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
348  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
349  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
350  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
351  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
352  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
353  * POSSIBILITY OF SUCH DAMAGE.
354  * 
355  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
356  */