FileDocCategorySizeDatePackage
DOMElementWriter.javaAPI DocApache Ant 1.7018971Wed Dec 13 06:16:18 GMT 2006org.apache.tools.ant.util

DOMElementWriter

public class DOMElementWriter extends Object
Writes a DOM tree to a given Writer. warning: this utility currently does not declare XML Namespaces.

Utility class used by {@link org.apache.tools.ant.XmlLogger XmlLogger} and org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter XMLJUnitResultFormatter}.

Fields Summary
private static final String
NS
prefix for genefrated prefixes
private boolean
xmlDeclaration
xml declaration is on by default
private XmlNamespacePolicy
namespacePolicy
XML Namespaces are ignored by default.
private HashMap
nsPrefixMap
Map (URI to prefix) of known namespaces.
private int
nextPrefix
Number of generated prefix to use next.
private HashMap
nsURIByElement
Map (Element to URI) of namespaces defined on a given element.
private static String
lSep
protected String[]
knownEntities
Don't try to be too smart but at least recognize the predefined entities.
Constructors Summary
public DOMElementWriter()
Create an element writer. The ?xml? declaration will be included, namespaces ignored.

    
public DOMElementWriter(boolean xmlDeclaration)
Create an element writer XML namespaces will be ignored.

param
xmlDeclaration flag to indicate whether the ?xml? declaration should be included.
since
Ant1.7

        this(xmlDeclaration, XmlNamespacePolicy.IGNORE);
    
public DOMElementWriter(boolean xmlDeclaration, XmlNamespacePolicy namespacePolicy)
Create an element writer XML namespaces will be ignored.

param
xmlDeclaration flag to indicate whether the ?xml? declaration should be included.
param
namespacePolicy the policy to use.
since
Ant1.7

        this.xmlDeclaration = xmlDeclaration;
        this.namespacePolicy = namespacePolicy;
    
Methods Summary
private voidaddNSDefinition(org.w3c.dom.Element element, java.lang.String uri)

        ArrayList al = (ArrayList) nsURIByElement.get(element);
        if (al == null) {
            al = new ArrayList();
            nsURIByElement.put(element, al);
        }
        al.add(uri);
    
public voidcloseElement(org.w3c.dom.Element element, java.io.Writer out, int indent, java.lang.String indentWith, boolean hasChildren)
Writes a DOM tree to a stream.

param
element the Root DOM element of the tree
param
out where to send the output
param
indent number of
param
indentWith string that should be used to indent the corresponding tag.
param
hasChildren if true indent.
throws
IOException if an error happens while writing to the stream.

        // If we had child elements, we need to indent before we close
        // the element, otherwise we're on the same line and don't need
        // to indent
        if (hasChildren) {
            for (int i = 0; i < indent; i++) {
                out.write(indentWith);
            }
        }

        // Write element close
        out.write("</");
        if (namespacePolicy.qualifyElements) {
            String uri = getNamespaceURI(element);
            String prefix = (String) nsPrefixMap.get(uri);
            if (prefix != null && !"".equals(prefix)) {
                out.write(prefix);
                out.write(":");
            }
            removeNSDefinitions(element);
        }
        out.write(element.getTagName());
        out.write(">");
        out.write(lSep);
        out.flush();
    
public java.lang.Stringencode(java.lang.String value)
Escape <, > & ', " as their entities and drop characters that are illegal in XML documents.

param
value the string to encode.
return
the encoded string.

        StringBuffer sb = new StringBuffer();
        int len = value.length();
        for (int i = 0; i < len; i++) {
            char c = value.charAt(i);
            switch (c) {
            case '<":
                sb.append("<");
                break;
            case '>":
                sb.append(">");
                break;
            case '\'":
                sb.append("'");
                break;
            case '\"":
                sb.append(""");
                break;
            case '&":
                int nextSemi = value.indexOf(";", i);
                if (nextSemi < 0
                    || !isReference(value.substring(i, nextSemi + 1))) {
                    sb.append("&");
                } else {
                    sb.append('&");
                }
                break;
            default:
                if (isLegalCharacter(c)) {
                    sb.append(c);
                }
                break;
            }
        }
        return sb.substring(0);
    
public java.lang.Stringencodedata(java.lang.String value)
Drop characters that are illegal in XML documents.

Also ensure that we are not including an ]]> marker by replacing that sequence with &#x5d;&#x5d;&gt;.

See XML 1.0 2.2 http://www.w3.org/TR/1998/REC-xml-19980210#charsets and 2.7 http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect.

param
value the value to be encoded.
return
the encoded value.

        StringBuffer sb = new StringBuffer();
        int len = value.length();
        for (int i = 0; i < len; ++i) {
            char c = value.charAt(i);
            if (isLegalCharacter(c)) {
                sb.append(c);
            }
        }

        String result = sb.substring(0);
        int cdEnd = result.indexOf("]]>");
        while (cdEnd != -1) {
            sb.setLength(cdEnd);
            sb.append("]]>")
                .append(result.substring(cdEnd + 3));
            result = sb.substring(0);
            cdEnd = result.indexOf("]]>");
        }

        return result;
    
private static java.lang.StringgetNamespaceURI(org.w3c.dom.Node n)

        String uri = n.getNamespaceURI();
        if (uri == null) {
            // FIXME: Is "No Namespace is Empty Namespace" really OK?
            uri = "";
        }
        return uri;
    
public booleanisLegalCharacter(char c)
Is the given character allowed inside an XML document?

See XML 1.0 2.2 http://www.w3.org/TR/1998/REC-xml-19980210#charsets.

param
c the character to test.
return
true if the character is allowed.
since
1.10, Ant 1.5

        if (c == 0x9 || c == 0xA || c == 0xD) {
            return true;
        } else if (c < 0x20) {
            return false;
        } else if (c <= 0xD7FF) {
            return true;
        } else if (c < 0xE000) {
            return false;
        } else if (c <= 0xFFFD) {
            return true;
        }
        return false;
    
public booleanisReference(java.lang.String ent)
Is the given argument a character or entity reference?

param
ent the value to be checked.
return
true if it is an entity.

        if (!(ent.charAt(0) == '&") || !ent.endsWith(";")) {
            return false;
        }

        if (ent.charAt(1) == '#") {
            if (ent.charAt(2) == 'x") {
                try {
                    Integer.parseInt(ent.substring(3, ent.length() - 1), 16);
                    return true;
                } catch (NumberFormatException nfe) {
                    return false;
                }
            } else {
                try {
                    Integer.parseInt(ent.substring(2, ent.length() - 1));
                    return true;
                } catch (NumberFormatException nfe) {
                    return false;
                }
            }
        }

        String name = ent.substring(1, ent.length() - 1);
        for (int i = 0; i < knownEntities.length; i++) {
            if (name.equals(knownEntities[i])) {
                return true;
            }
        }
        return false;
    
public voidopenElement(org.w3c.dom.Element element, java.io.Writer out, int indent, java.lang.String indentWith)
Writes the opening tag - including all attributes - corresponding to a DOM element.

param
element the DOM element to write
param
out where to send the output
param
indent number of
param
indentWith string that should be used to indent the corresponding tag.
throws
IOException if an error happens while writing to the stream.

        openElement(element, out, indent, indentWith, true);
    
public voidopenElement(org.w3c.dom.Element element, java.io.Writer out, int indent, java.lang.String indentWith, boolean hasChildren)
Writes the opening tag - including all attributes - corresponding to a DOM element.

param
element the DOM element to write
param
out where to send the output
param
indent number of
param
indentWith string that should be used to indent the corresponding tag.
param
hasChildren whether this element has children.
throws
IOException if an error happens while writing to the stream.
since
Ant 1.7

        // Write indent characters
        for (int i = 0; i < indent; i++) {
            out.write(indentWith);
        }

        // Write element
        out.write("<");
        if (namespacePolicy.qualifyElements) {
            String uri = getNamespaceURI(element);
            String prefix = (String) nsPrefixMap.get(uri);
            if (prefix == null) {
                if (nsPrefixMap.isEmpty()) {
                    // steal default namespace
                    prefix = "";
                } else {
                    prefix = NS + (nextPrefix++);
                }
                nsPrefixMap.put(uri, prefix);
                addNSDefinition(element, uri);
            }
            if (!"".equals(prefix)) {
                out.write(prefix);
                out.write(":");
            }
        }
        out.write(element.getTagName());

        // Write attributes
        NamedNodeMap attrs = element.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            Attr attr = (Attr) attrs.item(i);
            out.write(" ");
            if (namespacePolicy.qualifyAttributes) {
                String uri = getNamespaceURI(attr);
                String prefix = (String) nsPrefixMap.get(uri);
                if (prefix == null) {
                    prefix = NS + (nextPrefix++);
                    nsPrefixMap.put(uri, prefix);
                    addNSDefinition(element, uri);
                }
                out.write(prefix);
                out.write(":");
            }
            out.write(attr.getName());
            out.write("=\"");
            out.write(encode(attr.getValue()));
            out.write("\"");
        }

        // write namespace declarations
        ArrayList al = (ArrayList) nsURIByElement.get(element);
        if (al != null) {
            Iterator iter = al.iterator();
            while (iter.hasNext()) {
                String uri = (String) iter.next();
                String prefix = (String) nsPrefixMap.get(uri);
                out.write(" xmlns");
                if (!"".equals(prefix)) {
                    out.write(":");
                    out.write(prefix);
                }
                out.write("=\"");
                out.write(uri);
                out.write("\"");
            }
        }

        if (hasChildren) {
            out.write(">");
        } else {
            removeNSDefinitions(element);
            out.write(" />");
            out.write(lSep);
            out.flush();
        }
    
private voidremoveNSDefinitions(org.w3c.dom.Element element)

        ArrayList al = (ArrayList) nsURIByElement.get(element);
        if (al != null) {
            Iterator iter = al.iterator();
            while (iter.hasNext()) {
                nsPrefixMap.remove(iter.next());
            }
            nsURIByElement.remove(element);
        }
    
public voidwrite(org.w3c.dom.Element root, java.io.OutputStream out)
Writes a DOM tree to a stream in UTF8 encoding. Note that it prepends the <?xml version='1.0' encoding='UTF-8'?> if the xmlDeclaration field is true. The indent number is set to 0 and a 2-space indent.

param
root the root element of the DOM tree.
param
out the outputstream to write to.
throws
IOException if an error happens while writing to the stream.

    // CheckStyle:VisibilityModifier ON


                                                                       
            
        Writer wri = new OutputStreamWriter(out, "UTF8");
        writeXMLDeclaration(wri);
        write(root, wri, 0, "  ");
        wri.flush();
    
public voidwrite(org.w3c.dom.Element element, java.io.Writer out, int indent, java.lang.String indentWith)
Writes a DOM tree to a stream.

param
element the Root DOM element of the tree
param
out where to send the output
param
indent number of
param
indentWith string that should be used to indent the corresponding tag.
throws
IOException if an error happens while writing to the stream.


        // Write child elements and text
        NodeList children = element.getChildNodes();
        boolean hasChildren = (children.getLength() > 0);
        boolean hasChildElements = false;
        openElement(element, out, indent, indentWith, hasChildren);

        if (hasChildren) {
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);

                switch (child.getNodeType()) {

                case Node.ELEMENT_NODE:
                    hasChildElements = true;
                    if (i == 0) {
                        out.write(lSep);
                    }
                    write((Element) child, out, indent + 1, indentWith);
                    break;

                case Node.TEXT_NODE:
                    out.write(encode(child.getNodeValue()));
                    break;

                case Node.COMMENT_NODE:
                    out.write("<!--");
                    out.write(encode(child.getNodeValue()));
                    out.write("-->");
                    break;

                case Node.CDATA_SECTION_NODE:
                    out.write("<![CDATA[");
                    out.write(encodedata(((Text) child).getData()));
                    out.write("]]>");
                    break;

                case Node.ENTITY_REFERENCE_NODE:
                    out.write('&");
                    out.write(child.getNodeName());
                    out.write(';");
                    break;

                case Node.PROCESSING_INSTRUCTION_NODE:
                    out.write("<?");
                    out.write(child.getNodeName());
                    String data = child.getNodeValue();
                    if (data != null && data.length() > 0) {
                        out.write(' ");
                        out.write(data);
                    }
                    out.write("?>");
                    break;
                default:
                    // Do nothing
                }
            }
            closeElement(element, out, indent, indentWith, hasChildElements);
        }
    
public voidwriteXMLDeclaration(java.io.Writer wri)
Writes the XML declaration if xmlDeclaration is true.

param
wri the writer to write to.
throws
IOException if there is an error.
since
Ant 1.7.0

        if (xmlDeclaration) {
            wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        }