1   /*
2    * Copyright 2001-2004 (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    * $Id: TestXMLWriter.java,v 1.22 2004/09/01 19:37:58 maartenc Exp $
8    */
9   
10  package org.dom4j;
11  
12  import java.io.ByteArrayInputStream;
13  import java.io.ByteArrayOutputStream;
14  import java.io.StringReader;
15  import java.io.StringWriter;
16  
17  import junit.framework.Test;
18  import junit.framework.TestSuite;
19  import junit.textui.TestRunner;
20  
21  import org.dom4j.io.OutputFormat;
22  import org.dom4j.io.SAXReader;
23  import org.dom4j.io.XMLWriter;
24  import org.dom4j.tree.BaseElement;
25  import org.dom4j.tree.DefaultDocument;
26  import org.xml.sax.ContentHandler;
27  import org.xml.sax.SAXException;
28  import org.xml.sax.helpers.AttributesImpl;
29  
30  /*** A simple test harness to check that the XML Writer works
31    *
32    * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
33    * @version $Revision: 1.22 $
34    */
35  public class TestXMLWriter extends AbstractTestCase {
36  
37      protected static final boolean VERBOSE = false;
38      
39      
40      public static void main( String[] args ) {
41          TestRunner.run( suite() );
42      }
43      
44      public static Test suite() {
45          return new TestSuite( TestXMLWriter.class );
46      }
47      
48      public TestXMLWriter(String name) {
49          super(name);
50      }
51  
52      // Test case(s)
53      //-------------------------------------------------------------------------                    
54      public void testWriter() throws Exception {
55          Object object = document;
56          StringWriter out = new StringWriter();
57          
58          XMLWriter writer = new XMLWriter( out );
59          writer.write( object );
60          writer.close();
61          
62          String text = out.toString();
63              
64          if ( VERBOSE ) {
65              log( "Text output is ["  );
66              log( text );
67              log( "]. Done" );
68          }
69          
70          assertTrue( "Output text is bigger than 10 characters", text.length() > 10 );
71      }        
72      
73      public void testEncodingFormats() throws Exception {
74          testEncoding( "UTF-8" );
75          testEncoding( "UTF-16" );
76          testEncoding( "ISO-8859-1" );
77      }
78  
79      protected void testEncoding(String encoding) throws Exception {
80          ByteArrayOutputStream out = new ByteArrayOutputStream();
81          
82          OutputFormat format = OutputFormat.createPrettyPrint();
83          format.setEncoding( encoding );
84          XMLWriter writer = new XMLWriter( out, format );
85          writer.write( document );
86          writer.close();
87          
88          log( "Wrote to encoding: " + encoding );
89      }
90      
91      public void testWriterBug() throws Exception {        
92          Element project = new BaseElement("project"); 
93          Document doc = new DefaultDocument(project); 
94  
95          ByteArrayOutputStream out = new ByteArrayOutputStream();
96          XMLWriter writer = new XMLWriter(out, new OutputFormat("\t", true, "ISO-8859-1")); 
97          writer.write(doc); 
98          
99          ByteArrayInputStream in = new ByteArrayInputStream( out.toByteArray() );
100         SAXReader reader = new SAXReader();
101         Document doc2 = reader.read( in );
102         
103         assertTrue( "Generated document has a root element", doc2.getRootElement() != null );
104         assertEquals( "Generated document has corrent named root element", doc2.getRootElement().getName(), "project" );
105     }
106     
107     public void testNamespaceBug() throws Exception {        
108         Document doc = DocumentHelper.createDocument();
109         
110         Element root = doc.addElement("root","ns1");
111         Element child1 = root.addElement("joe","ns2");
112         child1.addElement("zot","ns1");
113         
114         StringWriter out = new StringWriter();
115         XMLWriter writer = new XMLWriter(
116             out,
117             OutputFormat.createPrettyPrint() 
118         );
119         writer.write(doc);
120         String text = out.toString();
121         
122         //System.out.println( "Generated:" + text );
123         
124         Document doc2 = DocumentHelper.parseText( text );
125         root = doc2.getRootElement();
126         assertEquals( "root has correct namespace", "ns1", root.getNamespaceURI() );
127         
128         Element joe = (Element) root.elementIterator().next();
129         assertEquals( "joe has correct namespace", "ns2", joe.getNamespaceURI() );
130         
131         Element zot = (Element) joe.elementIterator().next();
132         assertEquals( "zot has correct namespace", "ns1", zot.getNamespaceURI() );
133     }
134     
135     /*** This test harness was supplied by Lari Hotari */
136     public void testContentHandler() throws Exception {
137         StringWriter out = new StringWriter();
138     OutputFormat format = OutputFormat.createPrettyPrint();
139     format.setEncoding("iso-8859-1");
140     XMLWriter writer = new XMLWriter(out, format);
141         generateXML(writer);
142     writer.close();
143     String text = out.toString();
144 
145         if ( VERBOSE ) {
146             log( "Created XML" );
147             log( text );
148         }
149         
150         // now lets parse the output and test it with XPath
151         Document doc = DocumentHelper.parseText( text );
152         String value = doc.valueOf( "/processes[@name='arvojoo']" );
153         assertEquals( "Document contains the correct text", "jeejee", value );
154     }
155 
156     /*** This test was provided by Manfred Lotz */
157     public void testWhitespaceBug() throws Exception {
158         Document doc = DocumentHelper.parseText(
159             "<notes> This is a      multiline\n\rentry</notes>"
160         );
161         
162         OutputFormat format = new OutputFormat();
163         format.setEncoding("UTF-8");
164         format.setIndentSize(4);
165         format.setNewlines(true);
166         format.setTrimText(true);
167         format.setExpandEmptyElements(true);
168         
169         StringWriter buffer = new StringWriter();
170         XMLWriter writer = new XMLWriter(buffer, format);
171         writer.write( doc );
172         
173         String xml = buffer.toString();
174         log( xml );
175         
176         Document doc2 = DocumentHelper.parseText( xml );
177         String text = doc2.valueOf( "/notes" );
178         String expected = "This is a multiline entry";
179         
180         assertEquals( "valueOf() returns the correct text padding", expected, text );
181         
182         assertEquals( "getText() returns the correct text padding", expected, doc2.getRootElement().getText() );
183     }
184     
185     /*** This test was provided by Manfred Lotz */
186     public void testWhitespaceBug2() throws Exception {
187         Document doc = DocumentHelper.createDocument();
188         Element root = doc.addElement( "root" );
189         Element meaning = root.addElement( "meaning" );
190         meaning.addText( "to li" );
191         meaning.addText( "ve" );
192         
193         OutputFormat format = new OutputFormat();
194         format.setEncoding("UTF-8");
195         format.setIndentSize(4);
196         format.setNewlines(true);
197         format.setTrimText(true);
198         format.setExpandEmptyElements(true);
199         
200         StringWriter buffer = new StringWriter();
201         XMLWriter writer = new XMLWriter(buffer, format);
202         writer.write( doc );
203         
204         String xml = buffer.toString();
205         log( xml );
206         
207         Document doc2 = DocumentHelper.parseText( xml );
208         String text = doc2.valueOf( "/root/meaning" );
209         String expected = "to live";
210         
211         assertEquals( "valueOf() returns the correct text padding", expected, text );
212         
213         assertEquals( "getText() returns the correct text padding", expected, doc2.getRootElement().element("meaning").getText() );
214     }
215     
216     public void testPadding() throws Exception {
217         Document doc = DocumentFactory.getInstance().createDocument();
218         Element root = doc.addElement("root");
219         root.addText("prefix");
220         root.addElement("b");
221         root.addText("suffix");
222         
223         OutputFormat format = new OutputFormat("", false);
224         format.setOmitEncoding(true);
225         format.setSuppressDeclaration(true);
226         format.setExpandEmptyElements(true);
227         format.setPadText(true);
228         //format.setTrimText(true);
229         
230         StringWriter buffer = new StringWriter();
231         XMLWriter writer = new XMLWriter(buffer, format);
232         writer.write(doc);
233         String xml = buffer.toString();
234         
235         System.out.println("xml: " + xml);
236         String expected = "<root>prefix <b></b> suffix</root>";
237         assertEquals(expected, xml);
238     }
239     
240     /*
241      * This must be tested manually to see if the layout is correct.
242      */
243     public void testPrettyPrinting() throws Exception {
244         Document doc = DocumentFactory.getInstance().createDocument(); 
245         doc.addElement("summary").addAttribute("date", "6/7/8").addElement("orderline").addText("puffins").addElement("ranjit").addComment("Ranjit is a happy Puffin"); 
246         XMLWriter writer = new XMLWriter(System.out, OutputFormat.createPrettyPrint()); 
247         writer.write(doc);
248 
249         doc = DocumentFactory.getInstance().createDocument(); 
250         doc.addElement("summary").addAttribute("date", "6/7/8").addElement("orderline").addText("puffins").addElement("ranjit").addComment("Ranjit is a happy Puffin").addComment("another comment").addElement("anotherElement"); 
251         writer.write(doc);
252     }
253 
254     public void testAttributeQuotes() throws Exception {
255         Document doc = DocumentFactory.getInstance().createDocument();
256         doc.addElement("root").addAttribute("test", "text with ' in it");
257         StringWriter out = new StringWriter();
258         XMLWriter writer = new XMLWriter(out, OutputFormat.createCompactFormat());
259         writer.write(doc);
260         System.out.println(out.toString());
261         assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root test=\"text with ' in it\"/>", out.toString());
262     }
263     
264     public void testBug868408() throws Exception {
265         Document doc = parseDocument("/xml/web.xml");
266         Document doc2 = DocumentHelper.parseText(doc.asXML());
267         assertEquals(doc.asXML(), doc2.asXML());
268     }
269     
270     public void testBug923882() throws Exception {
271         Document doc = DocumentFactory.getInstance().createDocument();
272         Element root = doc.addElement("root");
273         root.addText("this is ");
274         root.addText(" sim");
275         root.addText("ple text ");
276         root.addElement("child");
277         root.addText(" contai");
278         root.addText("ning spaces and");
279         root.addText(" multiple textnodes");
280         OutputFormat format = new OutputFormat();
281         format.setEncoding("UTF-8");
282         format.setIndentSize(4);
283         format.setNewlines(true);
284         format.setTrimText(true);
285         format.setExpandEmptyElements(true);
286         StringWriter buffer = new StringWriter();
287         XMLWriter writer = new XMLWriter(buffer, format);
288         writer.write( doc );
289         String xml = buffer.toString();
290         log( xml );
291         int start = xml.indexOf("<root"),
292                 end = xml.indexOf("/root>")+6;
293         String eol = "\n"; //System.getProperty("line.separator");
294         String expected = 
295                 "<root>this is simple text" + eol +
296                 "    <child></child>containing spaces and multiple textnodes" + eol +
297                 "</root>";
298         System.out.println("Expected:"); System.out.println(expected);
299         System.out.println("Obtained:"); System.out.println(xml.substring(start, end));
300         assertEquals(expected, xml.substring(start, end));
301     }
302 
303     public void testEscapeXML() throws Exception {
304         ByteArrayOutputStream os = new ByteArrayOutputStream();
305         OutputFormat format = new OutputFormat(null,false,"ISO-8859-2");
306         format.setSuppressDeclaration(true);
307         XMLWriter writer = new XMLWriter(os,format);
308         
309         Document document = DocumentFactory.getInstance().createDocument();
310         Element root = document.addElement("root");
311         root.setText("bla &#c bla");
312         
313         writer.write(document);
314         String result = os.toString();
315         System.out.println(result);
316         Document doc2 = DocumentHelper.parseText(result);
317         doc2.normalize();       // merges adjacant Text nodes
318         System.out.println(doc2.getRootElement().getText());
319         assertNodesEqual(document, doc2);
320     }
321     
322     public void testWriteEntities() throws Exception {
323         String xml = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" +
324                      "<!DOCTYPE xml [<!ENTITY copy \"&#169;\"> " +
325                                     "<!ENTITY trade \"&#8482;\"> " +
326                                     "<!ENTITY deg \"&#x00b0;\"> " +
327                                     "<!ENTITY gt \"&#62;\"> " +
328                                     "<!ENTITY sup2 \"&#x00b2;\"> " +
329                                     "<!ENTITY frac14 \"&#x00bc;\"> " +
330                                     "<!ENTITY quot \"&#34;\"> " +
331                                     "<!ENTITY frac12 \"&#x00bd;\"> " +
332                                     "<!ENTITY euro \"&#x20ac;\"> " +
333                                     "<!ENTITY Omega \"&#937;\"> ]>\n" +
334                      "<root />";
335         
336         SAXReader reader = new SAXReader("org.apache.xerces.parsers.SAXParser");
337         reader.setIncludeInternalDTDDeclarations(true);
338         
339         Document doc = reader.read(new StringReader(xml));
340         StringWriter wr = new StringWriter();
341         XMLWriter writer = new XMLWriter(wr);
342         writer.write(doc);
343         
344         String xml2 = wr.toString();
345         System.out.println(xml2);
346         Document doc2 = DocumentHelper.parseText(xml2);
347         
348         assertNodesEqual(doc, doc2);
349     }
350     
351     public void testEscapeChars() throws Exception {
352     	Document document = DocumentFactory.getInstance().createDocument();
353     	Element root = document.addElement("root");
354     	root.setText("blahblah " + '\u008f');
355     	
356     	XMLWriter writer = new XMLWriter();
357     	StringWriter strWriter = new StringWriter();
358     	writer.setWriter(strWriter);
359     	writer.setMaximumAllowedCharacter(127);
360     	writer.write(document);
361     	String xml = strWriter.toString();
362     }
363     
364     public void testEscapeText() throws SAXException {
365     	StringWriter writer = new StringWriter();
366     	XMLWriter xmlWriter = new XMLWriter(writer);
367     	xmlWriter.setEscapeText(false);
368     	
369     	String txt = "<test></test>";
370     	
371     	xmlWriter.startDocument();
372     	xmlWriter.characters(txt.toCharArray(), 0, txt.length());
373     	xmlWriter.endDocument();
374     	
375     	String output = writer.toString();
376     	System.out.println(output);
377     	assertTrue(output.indexOf("<test>") != -1);
378     }
379     
380     protected org.dom4j.Document parseDocument(String file) throws Exception {
381         SAXReader reader = new SAXReader();
382         return reader.read(getClass().getResource(file));
383     }
384 
385     
386     protected void generateXML(ContentHandler handler) throws SAXException {
387         handler.startDocument();
388         AttributesImpl attrs = new AttributesImpl();
389         attrs.clear();
390         attrs.addAttribute("","","name","CDATA", "arvojoo");
391         handler.startElement("","","processes",attrs);
392         String text="jeejee";
393         char textch[] = text.toCharArray();
394         handler.characters(textch,0,textch.length);
395         handler.endElement("","","processes" );
396         handler.endDocument();
397     }
398 }
399 
400 
401 
402 
403 /*
404  * Redistribution and use of this software and associated documentation
405  * ("Software"), with or without modification, are permitted provided
406  * that the following conditions are met:
407  *
408  * 1. Redistributions of source code must retain copyright
409  *    statements and notices.  Redistributions must also contain a
410  *    copy of this document.
411  *
412  * 2. Redistributions in binary form must reproduce the
413  *    above copyright notice, this list of conditions and the
414  *    following disclaimer in the documentation and/or other
415  *    materials provided with the distribution.
416  *
417  * 3. The name "DOM4J" must not be used to endorse or promote
418  *    products derived from this Software without prior written
419  *    permission of MetaStuff, Ltd.  For written permission,
420  *    please contact dom4j-info@metastuff.com.
421  *
422  * 4. Products derived from this Software may not be called "DOM4J"
423  *    nor may "DOM4J" appear in their names without prior written
424  *    permission of MetaStuff, Ltd. DOM4J is a registered
425  *    trademark of MetaStuff, Ltd.
426  *
427  * 5. Due credit should be given to the DOM4J Project - 
428  *    http://www.dom4j.org
429  *
430  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
431  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
432  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
433  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
434  * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
435  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
436  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
437  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
438  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
439  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
440  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
441  * OF THE POSSIBILITY OF SUCH DAMAGE.
442  *
443  * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
444  *
445  * $Id: TestXMLWriter.java,v 1.22 2004/09/01 19:37:58 maartenc Exp $
446  */