如何让 Java.xml.Transformer 输出一个 xml 而没有任何无用的 space 或换行符?

How to let Java.xml.Transformer output a xml without any useless space or line break?

我现在的代码:

import org.w3c.dom.Node;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;

private String getStringByJAXP(Node input) {
        StreamResult xmlOutput;
        try {
            xmlOutput = new StreamResult(new StringWriter());
            transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            transformer.transform(new DOMSource(input), xmlOutput);
        } catch (TransformerException e) {
            throw new IllegalArgumentException();
        }
        return xmlOutput.getWriter().toString();
    }

输出:

<aaa>
    <a>text a</a>
    <b>
        <c>text c</c>
    </b>
    <f>
        <g><h a="xxx"/></g>
    </f>
</aaa>

但是我想输出如下:

<aaa><a>text a</a><b><c>text c</c></b><f><g><h a="xxx" /></g></f></aaa>

请注意,我无法通过一些简单的字符串替换来完成该任务,因为不应替换 <a>text a</a> 中的 space(<a>texta</a><a>text a</a>).

编辑:

OutputKeys.INDENT, "no" 无效。更新代码:

private String getStringByJAXP(Node input) {
    StreamResult xmlOutput;
    try {
        xmlOutput = new StreamResult(new StringWriter());
        transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
        transformer.transform(new DOMSource(input), xmlOutput);
    } catch (TransformerException e) {
        throw new IllegalArgumentException();
    }
    return xmlOutput.getWriter().toString();
}

我曾经遇到过类似的情况。 我首先尝试了 transformer.setOutputProperty(OutputKeys.INDENT,"no");,但这没有用。 问题是我的原始节点有额外的 "new line" 个文本节点。

Strip whitespace and newlines from XML in Java 的答案为我修复了它。基本上,您只需在转换父节点之前删除不需要的文本节点。

我最终使用了这个:

public static void trimWhitespace(Node node)
{
    NodeList children = node.getChildNodes();
    for(int i = 0; i < children.getLength(); ++i) {
        Node child = children.item(i);
        if(child.getNodeType() == Node.TEXT_NODE) {
            child.setTextContent(child.getTextContent().trim());
        }
        trimWhitespace(child);
    }
}

您可以将 XSLT 样式表传递给您的 Transformer,其优点是您不必解析文档两次。

InputStream xsltStream = getClass().getResourceAsStream("trim-whitespace.xslt");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(xsltStream));

trim-whitespace.xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- copy all elements as they are -->
    <xsl:template match="*">
        <xsl:copy>
            <xsl:copy-of select="@*" />
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*/text()[not(normalize-space())]" />
</xsl:stylesheet>