Refactoring XMLUtil.write to deal with *part of* #61938 (not enough to make the IDE work under Mustang b46 release55_dev_root version-2-3-33 version-2-3-35
authorjglick@netbeans.org
Tue, 09 Aug 2005 03:11:41 +0000
changeset 5221c7cc713d3d
parent 51 6848ca729a9e
child 53 0ca6326c7f3c
Refactoring XMLUtil.write to deal with *part of* #61938 (not enough to make the IDE work under Mustang b46
however): try to use JAXP for serialization whenever possible, i.e. on JDK 1.5+.
openide.util/nbproject/project.properties
openide.util/src/org/openide/xml/XMLUtil.java
openide.util/test/unit/src/org/openide/xml/XMLUtilTest.java
     1.1 --- a/openide.util/nbproject/project.properties	Mon Aug 01 21:07:38 2005 +0000
     1.2 +++ b/openide.util/nbproject/project.properties	Tue Aug 09 03:11:41 2005 +0000
     1.3 @@ -6,14 +6,17 @@
     1.4  # http://www.sun.com/
     1.5  # 
     1.6  # The Original Code is NetBeans. The Initial Developer of the Original
     1.7 -# Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
     1.8 +# Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun
     1.9  # Microsystems, Inc. All Rights Reserved.
    1.10  
    1.11  module.jar.dir=lib
    1.12 +
    1.13 +# For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4:
    1.14 +test.unit.run.cp.extra=\
    1.15 +    ${libs/xerces.dir}/modules/ext/xerces-2.6.2.jar:\
    1.16 +    ${libs/xerces.dir}/modules/ext/xml-commons-dom-ranges-1.0.b2.jar
    1.17 +
    1.18  javadoc.title=Utilities API
    1.19  javadoc.main.page=org/openide/util/doc-files/api.html
    1.20  javadoc.arch=${basedir}/arch.xml
    1.21  javadoc.apichanges=${basedir}/apichanges.xml
    1.22 -#javadoc.check.failonerror=true
    1.23 -
    1.24 -
     2.1 --- a/openide.util/src/org/openide/xml/XMLUtil.java	Mon Aug 01 21:07:38 2005 +0000
     2.2 +++ b/openide.util/src/org/openide/xml/XMLUtil.java	Tue Aug 09 03:11:41 2005 +0000
     2.3 @@ -7,19 +7,39 @@
     2.4   * http://www.sun.com/
     2.5   *
     2.6   * The Original Code is NetBeans. The Initial Developer of the Original
     2.7 - * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
     2.8 + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun
     2.9   * Microsystems, Inc. All Rights Reserved.
    2.10   */
    2.11 +
    2.12  package org.openide.xml;
    2.13  
    2.14 +import java.io.CharConversionException;
    2.15 +import java.io.IOException;
    2.16 +import java.io.OutputStream;
    2.17 +import java.io.StringReader;
    2.18 +import java.lang.reflect.Method;
    2.19 +import javax.xml.parsers.DocumentBuilder;
    2.20 +import javax.xml.parsers.DocumentBuilderFactory;
    2.21 +import javax.xml.parsers.ParserConfigurationException;
    2.22 +import javax.xml.parsers.SAXParserFactory;
    2.23 +import javax.xml.transform.OutputKeys;
    2.24 +import javax.xml.transform.Result;
    2.25 +import javax.xml.transform.Source;
    2.26 +import javax.xml.transform.Transformer;
    2.27 +import javax.xml.transform.TransformerFactory;
    2.28 +import javax.xml.transform.dom.DOMSource;
    2.29 +import javax.xml.transform.stream.StreamResult;
    2.30 +import javax.xml.transform.stream.StreamSource;
    2.31  import org.openide.ErrorManager;
    2.32 -import org.w3c.dom.*;
    2.33 -import org.xml.sax.*;
    2.34 -
    2.35 -import java.io.*;
    2.36 -
    2.37 -import javax.xml.parsers.*;
    2.38 -
    2.39 +import org.w3c.dom.DOMException;
    2.40 +import org.w3c.dom.DOMImplementation;
    2.41 +import org.w3c.dom.Document;
    2.42 +import org.w3c.dom.DocumentType;
    2.43 +import org.xml.sax.EntityResolver;
    2.44 +import org.xml.sax.ErrorHandler;
    2.45 +import org.xml.sax.InputSource;
    2.46 +import org.xml.sax.SAXException;
    2.47 +import org.xml.sax.XMLReader;
    2.48  
    2.49  /**
    2.50   * Utility class collecting library methods related to XML processing.
    2.51 @@ -304,19 +324,101 @@
    2.52      }
    2.53  
    2.54      /**
    2.55 -     * Write Document into OutputStream using given encoding.
    2.56 -     * It is a shortcut for writing configurations etc. It guarantees
    2.57 -     * just that data will be written. Structure and indentation may change.
    2.58 -     *
    2.59 -     * @param doc DOM Document to be written
    2.60 +     * Identity transformation in XSLT with indentation added.
    2.61 +     * Just using the identity transform and calling
    2.62 +     * t.setOutputProperty(OutputKeys.INDENT, "yes");
    2.63 +     * t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    2.64 +     * does not work currently.
    2.65 +     * You really have to use this bogus stylesheet.
    2.66 +     * @see "JDK bug #5064280"
    2.67 +     */
    2.68 +    private static final String IDENTITY_XSLT_WITH_INDENT =
    2.69 +            "<xsl:stylesheet version='1.0' " + // NOI18N
    2.70 +            "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " + // NOI18N
    2.71 +            "xmlns:xalan='http://xml.apache.org/xslt' " + // NOI18N
    2.72 +            "exclude-result-prefixes='xalan'>" + // NOI18N
    2.73 +            "<xsl:output method='xml' indent='yes' xalan:indent-amount='4'/>" + // NOI18N
    2.74 +            "<xsl:template match='@*|node()'>" + // NOI18N
    2.75 +            "<xsl:copy>" + // NOI18N
    2.76 +            "<xsl:apply-templates select='@*|node()'/>" + // NOI18N
    2.77 +            "</xsl:copy>" + // NOI18N
    2.78 +            "</xsl:template>" + // NOI18N
    2.79 +            "</xsl:stylesheet>"; // NOI18N
    2.80 +    /**
    2.81 +     * Writes a DOM document to a stream.
    2.82 +     * The precise output format is not guaranteed but this method will attempt to indent it sensibly.
    2.83 +     * 
    2.84 +     * @param doc DOM document to be written
    2.85       * @param out data sink
    2.86 -     * @param enc XML defined encoding name (i.e. IANA defined, one of UTF-8, UNICODE, ASCII)
    2.87 -     *
    2.88 -     * @throws IOException if an I/O exception occurs
    2.89 +     * @param enc XML-defined encoding name (e.g. "UTF-8")
    2.90 +     * @throws IOException if JAXP fails or the stream cannot be written to
    2.91       */
    2.92 -    public static void write(Document doc, OutputStream out, String enc)
    2.93 -    throws IOException {
    2.94 -        XMLUtilImpl.write(doc, out, enc);
    2.95 +    public static void write(Document doc, OutputStream out, String enc) throws IOException {
    2.96 +        if (enc == null) {
    2.97 +            throw new NullPointerException("You must set an encoding; use \"UTF-8\" unless you have a good reason not to!"); // NOI18N
    2.98 +        }
    2.99 +        if (System.getProperty("java.specification.version").startsWith("1.4")) { // NOI18N
   2.100 +            // Hack for JDK 1.4. Using JAXP won't work; e.g. JDK bug #6308026.
   2.101 +            // Try using Xerces instead - let's hope it's loadable...
   2.102 +            try {
   2.103 +                writeXerces(doc, out, enc);
   2.104 +                return;
   2.105 +            } catch (ClassNotFoundException e) {
   2.106 +                throw (IOException) new IOException("You need to have xerces.jar available to use XMLUtil.write under JDK 1.4: " + e).initCause(e); // NOI18N
   2.107 +            } catch (Exception e) {
   2.108 +                throw (IOException) new IOException(e.toString()).initCause(e);
   2.109 +            }
   2.110 +        }
   2.111 +        try {
   2.112 +            Transformer t = TransformerFactory.newInstance().newTransformer(
   2.113 +                    new StreamSource(new StringReader(IDENTITY_XSLT_WITH_INDENT)));
   2.114 +            DocumentType dt = doc.getDoctype();
   2.115 +            if (dt != null) {
   2.116 +                String pub = dt.getPublicId();
   2.117 +                if (pub != null) {
   2.118 +                    t.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, pub);
   2.119 +                }
   2.120 +                t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, dt.getSystemId());
   2.121 +            }
   2.122 +            t.setOutputProperty(OutputKeys.ENCODING, enc);
   2.123 +            Source source = new DOMSource(doc);
   2.124 +            Result result = new StreamResult(out);
   2.125 +            t.transform(source, result);
   2.126 +        } catch (Exception e) {
   2.127 +            throw (IOException) new IOException(e.toString()).initCause(e);
   2.128 +        }
   2.129 +    }
   2.130 +    /**
   2.131 +     * Serialize a document using Xerces' library.
   2.132 +     * This library is available in the JDK starting with version 1.5 (where we do not need it anyway),
   2.133 +     * but in 1.4 you need to have Xerces loaded in the system somewhere.
   2.134 +     */
   2.135 +    private static void writeXerces(Document doc, OutputStream out, String encoding) throws ClassNotFoundException, Exception {
   2.136 +        ClassLoader cl = Thread.currentThread().getContextClassLoader();
   2.137 +        Class xmlSerializerClazz = Class.forName("org.apache.xml.serialize.XMLSerializer", true, cl); // NOI18N
   2.138 +        Class outputFormatClazz = Class.forName("org.apache.xml.serialize.OutputFormat", true, cl); // NOI18N
   2.139 +        Object xmlSerializer = xmlSerializerClazz.newInstance();
   2.140 +        Object outputFormat = outputFormatClazz.newInstance();
   2.141 +        Method setMethod = outputFormatClazz.getMethod("setMethod", new Class[] {String.class}); // NOI18N
   2.142 +        setMethod.invoke(outputFormat, new Object[] {"xml"}); // NOI18N
   2.143 +        Method setIndenting = outputFormatClazz.getMethod("setIndenting", new Class[] {Boolean.TYPE}); // NOI18N
   2.144 +        setIndenting.invoke(outputFormat, new Object[] {Boolean.TRUE}); // NOI18N
   2.145 +        Method setLineWidth = outputFormatClazz.getMethod("setLineWidth", new Class[] {Integer.TYPE}); // NOI18N
   2.146 +        setLineWidth.invoke(outputFormat, new Object[] {new Integer(0)});
   2.147 +        Method setLineSeparator = outputFormatClazz.getMethod("setLineSeparator", new Class[] {String.class}); // NOI18N
   2.148 +        setLineSeparator.invoke(outputFormat, new String[] {System.getProperty("line.separator")}); // NOI18N
   2.149 +        Method setOutputByteStream = xmlSerializerClazz.getMethod("setOutputByteStream", new Class[] {OutputStream.class}); // NOI18N
   2.150 +        setOutputByteStream.invoke(xmlSerializer, new Object[] {out});
   2.151 +        Method setEncoding = outputFormatClazz.getMethod("setEncoding", new Class[] {String.class}); // NOI18N
   2.152 +        setEncoding.invoke(outputFormat, new Object[] {encoding});
   2.153 +        Method setOutputFormat = xmlSerializerClazz.getMethod("setOutputFormat", new Class[] {outputFormatClazz}); // NOI18N
   2.154 +        setOutputFormat.invoke(xmlSerializer, new Object[] {outputFormat});
   2.155 +        Method setNamespaces = xmlSerializerClazz.getMethod("setNamespaces", new Class[] {Boolean.TYPE}); // NOI18N
   2.156 +        setNamespaces.invoke(xmlSerializer, new Object[] {Boolean.TRUE});
   2.157 +        Method asDOMSerializer = xmlSerializerClazz.getMethod("asDOMSerializer", new Class[0]); // NOI18N
   2.158 +        Object impl = asDOMSerializer.invoke(xmlSerializer, null);
   2.159 +        Method serialize = impl.getClass().getMethod("serialize", new Class[] {Document.class}); // NOI18N
   2.160 +        serialize.invoke(impl, new Object[] {doc});
   2.161      }
   2.162  
   2.163      /**
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/openide.util/test/unit/src/org/openide/xml/XMLUtilTest.java	Tue Aug 09 03:11:41 2005 +0000
     3.3 @@ -0,0 +1,282 @@
     3.4 +/*
     3.5 + *                 Sun Public License Notice
     3.6 + * 
     3.7 + * The contents of this file are subject to the Sun Public License
     3.8 + * Version 1.0 (the "License"). You may not use this file except in
     3.9 + * compliance with the License. A copy of the License is available at
    3.10 + * http://www.sun.com/
    3.11 + * 
    3.12 + * The Original Code is NetBeans. The Initial Developer of the Original
    3.13 + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun
    3.14 + * Microsystems, Inc. All Rights Reserved.
    3.15 + */
    3.16 +
    3.17 +package org.openide.xml;
    3.18 +
    3.19 +import java.io.ByteArrayInputStream;
    3.20 +import java.io.ByteArrayOutputStream;
    3.21 +import java.io.CharConversionException;
    3.22 +import java.io.IOException;
    3.23 +import java.io.StringReader;
    3.24 +import junit.framework.Test;
    3.25 +import org.netbeans.junit.NbTestCase;
    3.26 +import org.netbeans.junit.NbTestSuite;
    3.27 +import org.w3c.dom.Document;
    3.28 +import org.w3c.dom.DocumentType;
    3.29 +import org.w3c.dom.Element;
    3.30 +import org.w3c.dom.NodeList;
    3.31 +import org.xml.sax.EntityResolver;
    3.32 +import org.xml.sax.ErrorHandler;
    3.33 +import org.xml.sax.InputSource;
    3.34 +import org.xml.sax.SAXException;
    3.35 +import org.xml.sax.SAXParseException;
    3.36 +import org.xml.sax.XMLReader;
    3.37 +
    3.38 +public class XMLUtilTest extends NbTestCase {
    3.39 +    
    3.40 +    public XMLUtilTest(String testName) {
    3.41 +        super(testName);
    3.42 +    }
    3.43 +    
    3.44 +    public void testCreateXMLReader() {
    3.45 +        
    3.46 +        XMLReader parser = null;
    3.47 +        
    3.48 +        try {
    3.49 +            parser = XMLUtil.createXMLReader();
    3.50 +        } catch (Exception ex) {
    3.51 +            ex.printStackTrace();
    3.52 +        }
    3.53 +                
    3.54 +        // Add your test code below by replacing the default call to fail.
    3.55 +        if (parser == null) fail("Cannot create XML reader");
    3.56 +    }
    3.57 +    
    3.58 +    public void testCreateDocument() {
    3.59 +       
    3.60 +        Document doc = null;
    3.61 +        try {
    3.62 +            doc = XMLUtil.createDocument("root", null, null, null);
    3.63 +        } catch (Exception ex) {
    3.64 +            ex.printStackTrace();
    3.65 +        }
    3.66 +        
    3.67 +        // Add your test code below by replacing the default call to fail.
    3.68 +        if (doc == null) fail("The test case is empty.");
    3.69 +    }
    3.70 +    
    3.71 +    public void testWrite() throws Exception {
    3.72 +        String data = "<foo bar=\"val\"><baz/></foo>";
    3.73 +        Document doc = XMLUtil.parse(new InputSource(new StringReader(data)), false, true, null, null);
    3.74 +        //System.err.println("XMLUtil.parse impl class: " + doc.getClass().getName());
    3.75 +        Element el = doc.getDocumentElement();
    3.76 +        assertEquals("foo", el.getNodeName());
    3.77 +        assertEquals("val", el.getAttribute("bar"));
    3.78 +        NodeList l = el.getElementsByTagName("*");
    3.79 +        assertEquals(1, l.getLength());
    3.80 +        Element el2 = (Element)l.item(0);
    3.81 +        assertEquals("baz", el2.getLocalName());
    3.82 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
    3.83 +        XMLUtil.write(doc, baos, "UTF-8");
    3.84 +        String data2 = baos.toString("UTF-8");
    3.85 +        //System.err.println("testWrite: data2:\n" + data2);
    3.86 +        assertTrue(data2, data2.indexOf("foo") != -1);
    3.87 +        assertTrue(data2, data2.indexOf("bar") != -1);
    3.88 +        assertTrue(data2, data2.indexOf("baz") != -1);
    3.89 +        assertTrue(data2, data2.indexOf("val") != -1);
    3.90 +    }
    3.91 +    
    3.92 +    /** Test that read/write DOCTYPE works too. */
    3.93 +    public void testDocType() throws Exception {
    3.94 +        String data = "<!DOCTYPE foo PUBLIC \"The foo DTD\" \"http://nowhere.net/foo.dtd\"><foo><x/><x/></foo>";
    3.95 +        Document doc = XMLUtil.parse(new InputSource(new StringReader(data)), true, true, new Handler(), new Resolver());
    3.96 +        DocumentType t = doc.getDoctype();
    3.97 +        assertNotNull(t);
    3.98 +        assertEquals("foo", t.getName());
    3.99 +        assertEquals("The foo DTD", t.getPublicId());
   3.100 +        assertEquals("http://nowhere.net/foo.dtd", t.getSystemId());
   3.101 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
   3.102 +        XMLUtil.write(doc, baos, "UTF-8");
   3.103 +        String data2 = baos.toString("UTF-8");
   3.104 +        //System.err.println("data2:\n" + data2);
   3.105 +        assertTrue(data2, data2.indexOf("foo") != -1);
   3.106 +        assertTrue(data2, data2.indexOf("x") != -1);
   3.107 +        assertTrue(data2, data2.indexOf("DOCTYPE") != -1);
   3.108 +        assertTrue(data2, data2.indexOf("The foo DTD") != -1);
   3.109 +        assertTrue(data2, data2.indexOf("http://nowhere.net/foo.dtd") != -1);
   3.110 +    }
   3.111 +    private static final class Handler implements ErrorHandler {
   3.112 +        public void error(SAXParseException exception) throws SAXException {
   3.113 +            throw exception;
   3.114 +        }
   3.115 +        public void fatalError(SAXParseException exception) throws SAXException {
   3.116 +            throw exception;
   3.117 +        }
   3.118 +        public void warning(SAXParseException exception) throws SAXException {
   3.119 +            throw exception;
   3.120 +        }
   3.121 +    }
   3.122 +    private static final class Resolver implements EntityResolver {
   3.123 +        public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
   3.124 +            assertEquals("The foo DTD", publicId);
   3.125 +            assertEquals("http://nowhere.net/foo.dtd", systemId);
   3.126 +            String data = "<!ELEMENT foo (x+)><!ELEMENT x EMPTY>";
   3.127 +            return new InputSource(new StringReader(data));
   3.128 +        }
   3.129 +    }
   3.130 +    
   3.131 +    public void testToAttributeValue() throws IOException {
   3.132 +        String result = null;
   3.133 +        try {
   3.134 +            result = XMLUtil.toAttributeValue("\t\r\n &'<\"");
   3.135 +        } catch (CharConversionException ex) {            
   3.136 +        }
   3.137 +        
   3.138 +        assertEquals("Basic escape test failed", "\t\r\n &amp;&apos;&lt;&quot;", result);
   3.139 +        
   3.140 +        try {
   3.141 +            XMLUtil.toAttributeValue(new String(new byte[] { 0 }));
   3.142 +            fail("Forbidden character accepted.");
   3.143 +        } catch (CharConversionException ex) {            
   3.144 +        }
   3.145 +
   3.146 +        try {
   3.147 +            XMLUtil.toAttributeValue(new String(new byte[] { 31 }));
   3.148 +            fail("Forbidden character accepted.");
   3.149 +        } catch (CharConversionException ex) {            
   3.150 +        }        
   3.151 +    }
   3.152 +    
   3.153 +    public void testElementToContent() {
   3.154 +        String result = null;
   3.155 +        
   3.156 +        try {
   3.157 +            result = XMLUtil.toElementContent("]]>\t\r\n &<>");
   3.158 +        } catch (CharConversionException ex) {
   3.159 +        }
   3.160 +        
   3.161 +        assertEquals("Basic escape test failed", "]]&gt;\t\r\n &amp;&lt;>", result);
   3.162 +        
   3.163 +        try {
   3.164 +            XMLUtil.toElementContent(new String(new byte[] { 0 }));
   3.165 +            fail("Forbidden character accepted.");
   3.166 +        } catch (CharConversionException ex) {            
   3.167 +        }
   3.168 +
   3.169 +        try {
   3.170 +            XMLUtil.toElementContent(new String(new byte[] { 31 }));
   3.171 +            fail("Forbidden character accepted.");
   3.172 +        } catch (CharConversionException ex) {            
   3.173 +        }        
   3.174 +                
   3.175 +    }
   3.176 +    
   3.177 +    public void testToHex() {
   3.178 +        
   3.179 +        byte[] data = new byte[] {0, 1, 15, 16, (byte)255};
   3.180 +        String s = XMLUtil.toHex(data, 0, data.length);
   3.181 +        
   3.182 +        // Add your test code below by replacing the default call to fail.
   3.183 +        if (s.equalsIgnoreCase("00010f10ff") == false) {
   3.184 +            fail("toHex() =" + s);
   3.185 +        }
   3.186 +    }
   3.187 +    
   3.188 +    public void testFromHex() {
   3.189 +        
   3.190 +        char[] hex = "00010f10ff".toCharArray();
   3.191 +        try {
   3.192 +            byte[] ret = XMLUtil.fromHex(hex, 0, hex.length);
   3.193 +            if (ret[0] != 0 || ret[1] != 1 || ret[2] != 15 || ret[3] != 16 || ret[4] != (byte)255) {
   3.194 +                fail("fromHex()");
   3.195 +            }
   3.196 +        } catch (IOException ex) {
   3.197 +            fail(ex.getMessage());
   3.198 +        }
   3.199 +                
   3.200 +    }
   3.201 +    
   3.202 +    /**
   3.203 +     * Check that reading and writing namespaces works.
   3.204 +     * @see "#36294"
   3.205 +     */
   3.206 +    public void testNamespaces() throws Exception {
   3.207 +        String data = "<foo xmlns='bar'><baz/></foo>";
   3.208 +        Document doc = XMLUtil.parse(new InputSource(new StringReader(data)), false, true, null, null);
   3.209 +        //System.err.println("XMLUtil.parse impl class: " + doc.getClass().getName());
   3.210 +        Element el = doc.getDocumentElement();
   3.211 +        assertEquals("foo", el.getNodeName());
   3.212 +        assertEquals("foo", el.getTagName());
   3.213 +        assertEquals("foo", el.getLocalName());
   3.214 +        assertEquals("bar", el.getNamespaceURI());
   3.215 +        NodeList l = el.getElementsByTagName("*");
   3.216 +        assertEquals(1, l.getLength());
   3.217 +        Element el2 = (Element)l.item(0);
   3.218 +        assertEquals("baz", el2.getLocalName());
   3.219 +        assertEquals("bar", el2.getNamespaceURI());
   3.220 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
   3.221 +        XMLUtil.write(doc, baos, "UTF-8");
   3.222 +        String data2 = baos.toString("UTF-8");
   3.223 +        //System.err.println("testNamespaces: data2:\n" + data2);
   3.224 +        assertTrue(data2, data2.indexOf("foo") != -1);
   3.225 +        assertTrue(data2, data2.indexOf("bar") != -1);
   3.226 +        doc = XMLUtil.parse(new InputSource(new ByteArrayInputStream(baos.toByteArray())), false, true, null, null);
   3.227 +        el = doc.getDocumentElement();
   3.228 +        assertEquals("foo", el.getLocalName());
   3.229 +        assertEquals("bar", el.getNamespaceURI());
   3.230 +        l = el.getElementsByTagName("*");
   3.231 +        assertEquals(1, l.getLength());
   3.232 +        el2 = (Element)l.item(0);
   3.233 +        assertEquals("baz", el2.getLocalName());
   3.234 +        assertEquals("bar", el2.getNamespaceURI());
   3.235 +        doc = XMLUtil.createDocument("foo2", "bar2", null, null);
   3.236 +        //System.err.println("XMLUtil.createDocument impl class: " + doc.getClass().getName());
   3.237 +        doc.getDocumentElement().appendChild(doc.createElementNS("bar2", "baz2"));
   3.238 +        baos = new ByteArrayOutputStream();
   3.239 +        XMLUtil.write(doc, baos, "UTF-8");
   3.240 +        data2 = baos.toString("UTF-8");
   3.241 +        assertTrue(data2, data2.indexOf("foo2") != -1);
   3.242 +        assertTrue("namespace 'bar2' of root element mentioned in output: " + data2, data2.indexOf("bar2") != -1);
   3.243 +        doc = XMLUtil.parse(new InputSource(new ByteArrayInputStream(baos.toByteArray())), false, true, null, null);
   3.244 +        el = doc.getDocumentElement();
   3.245 +        assertEquals("foo2", el.getLocalName());
   3.246 +        assertEquals("bar2", el.getNamespaceURI());
   3.247 +        l = el.getElementsByTagName("*");
   3.248 +        assertEquals(1, l.getLength());
   3.249 +        el2 = (Element)l.item(0);
   3.250 +        assertEquals("baz2", el2.getLocalName());
   3.251 +        assertEquals("bar2", el2.getNamespaceURI());
   3.252 +    }
   3.253 +    
   3.254 +    /**
   3.255 +     * Check more namespace stuff, since JAXP has a lot of bugs...
   3.256 +     * @see "#6308026"
   3.257 +     */
   3.258 +    public void testNamespaces2() throws Exception {
   3.259 +        String data = "<root xmlns='root'/>";
   3.260 +        Document doc = XMLUtil.parse(new InputSource(new StringReader(data)), false, true, null, null);
   3.261 +        doc.getDocumentElement().appendChild(doc.createElementNS("child", "child"));
   3.262 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
   3.263 +        XMLUtil.write(doc, baos, "UTF-8");
   3.264 +        //System.err.println("testNamespaces2:\n" + baos);
   3.265 +        doc = XMLUtil.parse(new InputSource(new ByteArrayInputStream(baos.toByteArray())), false, true, null, null);
   3.266 +        Element el = doc.getDocumentElement();
   3.267 +        assertEquals("root", el.getLocalName());
   3.268 +        assertEquals("root", el.getNamespaceURI());
   3.269 +        NodeList l = el.getElementsByTagName("*");
   3.270 +        assertEquals(1, l.getLength());
   3.271 +        el = (Element) l.item(0);
   3.272 +        assertEquals("child", el.getLocalName());
   3.273 +        assertEquals("child", el.getNamespaceURI());
   3.274 +    }
   3.275 +    
   3.276 +    public void testIndentation() throws Exception {
   3.277 +        Document doc = XMLUtil.createDocument("root", null, null, null);
   3.278 +        doc.getDocumentElement().appendChild(doc.createElement("child"));
   3.279 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
   3.280 +        XMLUtil.write(doc, baos, "UTF-8");
   3.281 +        String data = baos.toString();
   3.282 +        assertTrue("had reasonable indentation in\n" + data, data.indexOf("<root>\n    <child/>\n</root>\n") != -1);
   3.283 +    }
   3.284 +    
   3.285 +}