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