18

使用 Java,我想获取以下格式的文档:

<tag1>
 <tag2>
    <![CDATA[  Some data ]]>
 </tag2>
</tag1>

并将其转换为:

<tag1><tag2><![CDATA[  Some data ]]></tag2></tag1>

我尝试了以下方法,但它没有给我我期望的结果:

DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
dbfac.setIgnoringElementContentWhitespace(true);
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.parse(new FileInputStream("/tmp/test.xml"));

Writer out = new StringWriter();
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "no");
tf.transform(new DOMSource(doc), new StreamResult(out));
System.out.println(out.toString());
4

6 回答 6

20

遵循@Luiggi Mendoza 问题评论中的说明的工作解决方案。

public static String trim(String input) {
    BufferedReader reader = new BufferedReader(new StringReader(input));
    StringBuffer result = new StringBuffer();
    try {
        String line;
        while ( (line = reader.readLine() ) != null)
            result.append(line.trim());
        return result.toString();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
于 2012-10-31T17:52:19.167 回答
14

递归遍历文档。删除任何内容为空白的文本节点。修剪任何具有非空白内容的文本节点。

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);
    }
}
于 2012-07-28T18:56:30.793 回答
6

正如另一个问题的答案中所记录的那样,相关函数将是DocumentBuilderFactory.setIgnoringElementContentWhitespace(),但是 - 正如这里已经指出的那样 - 该函数需要使用验证解析器,这需要 XML 模式或类似的。

因此,最好的办法是遍历从解析器获得的文档,并删除所有类型为 TEXT_NODE 的节点(或那些仅包含空格的 TEXT_NODE)。

于 2013-03-17T16:06:44.083 回答
1

我支持@jtahlborn 的回答。为了完整起见,我调整了他的解决方案以完全删除仅空白元素,而不是仅仅清除它们。

public static void stripEmptyElements(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) {
            if (child.getTextContent().trim().length() == 0) {
                child.getParentNode().removeChild(child);
                i--;
            }
        }
        stripEmptyElements(child);
    }
}
于 2020-11-03T08:59:42.510 回答
0

Java8+transformer 不会创建任何内容,但 Java10+transformer 会到处放置空行。我仍然想保留一个漂亮的缩进。这是我从任何 DOMElement 实例(例如doc.getDocumentElement()根节点)创建 xml 字符串的辅助函数。

public static String createXML(Element elem) throws Exception {
        DOMSource source = new DOMSource(elem);
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        //transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        //transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
        transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
        transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
        transformer.transform(source, result);

        // Java10-transformer adds unecessary empty lines, remove empty lines
        BufferedReader reader = new BufferedReader(new StringReader(writer.toString()));
        StringBuilder buf = new StringBuilder();
        try {
            final String NL = System.getProperty("line.separator", "\r\n");
            String line;
            while( (line=reader.readLine())!=null ) {
                if (!line.trim().isEmpty()) {
                    buf.append(line); 
                    buf.append(NL);
                }
            }
        } finally {
            reader.close();
        }
        return buf.toString();  //writer.toString();
    }
于 2019-02-13T10:12:54.603 回答
-4

试试这个代码。FileStream 中的read和方法忽略空格和缩进。write

try {
    File f1 = new File("source.xml");
    File f2 = new File("destination.xml");
    InputStream in = new FileInputStream(f1);  
    OutputStream out = new FileOutputStream(f2);

    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0){
    out.write(buf, 0, len);
}
in.close();
out.close();
System.out.println("File copied.");
} catch(FileNotFoundException ex){
    System.out.println(ex.getMessage() + " in the specified directory.");
    System.exit(0);
} catch(IOException e7){
    System.out.println(e7.getMessage());  
}
于 2012-07-28T19:04:37.813 回答