如何从 XML 文件中删除多余的空行?

Posted

技术标签:

【中文标题】如何从 XML 文件中删除多余的空行?【英文标题】:How to remove extra empty lines from XML file? 【发布时间】:2012-09-22 02:10:06 【问题描述】:

简而言之;我在 XML 文件中生成了许多空行,我正在寻找一种将它们删除的方法,以作为倾斜文件的一种方式。我该怎么做?

详细解释;我目前有这个 XML 文件:

<recent>
  <paths>
    <path>path1</path>
    <path>path2</path>
    <path>path3</path>
    <path>path4</path>
  </paths>
</recent>

我使用这个 Java 代码删除所有标签,并添加新标签:

public void savePaths( String recentFilePath ) 
    ArrayList<String> newPaths = getNewRecentPaths();
    Document recentDomObject = getXMLFile( recentFilePath );  // Get the <recent> element.
    NodeList pathNodes = recentDomObject.getElementsByTagName( "path" );   // Get all <path> nodes.

    //1. Remove all old path nodes :
        for ( int i = pathNodes.getLength() - 1; i >= 0; i-- )  
            Element pathNode = (Element)pathNodes.item( i );
            pathNode.getParentNode().removeChild( pathNode );
        

    //2. Save all new paths :
        Element pathsElement = (Element)recentDomObject.getElementsByTagName( "paths" ).item( 0 );   // Get the first <paths> node.

        for( String newPath: newPaths ) 
            Element newPathElement = recentDomObject.createElement( "path" );
            newPathElement.setTextContent( newPath );
            pathsElement.appendChild( newPathElement );
        

    //3. Save the XML changes :
        saveXMLFile( recentFilePath, recentDomObject ); 

多次执行此方法后,我得到一个结果正确的 XML 文件,但在“路径”标记之后和第一个“路径”标记之前有许多空行,如下所示:

<recent>
  <paths>





    <path>path5</path>
    <path>path6</path>
    <path>path7</path>
  </paths>
</recent>

有人知道怎么解决吗?

------------------------------------------ 编辑:添加getXMLFile(...)、saveXMLFile(...)代码。

public Document getXMLFile( String filePath )  
    File xmlFile = new File( filePath );

    try 
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document domObject = db.parse( xmlFile );
        domObject.getDocumentElement().normalize();

        return domObject;
     catch (Exception e) 
        e.printStackTrace();
    

    return null;


public void saveXMLFile( String filePath, Document domObject ) 
    File xmlOutputFile = null;
    FileOutputStream fos = null;

    try 
        xmlOutputFile = new File( filePath );
        fos = new FileOutputStream( xmlOutputFile );
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
        transformer.setOutputProperty( "http://xml.apache.org/xsltindent-amount", "2" );
        DOMSource xmlSource = new DOMSource( domObject );
        StreamResult xmlResult = new StreamResult( fos );
        transformer.transform( xmlSource, xmlResult );  // Save the XML file.
     catch (FileNotFoundException e) 
        e.printStackTrace();
     catch (TransformerConfigurationException e) 
        e.printStackTrace();
     catch (TransformerException e) 
        e.printStackTrace();
     finally 
        if (fos != null)
            try 
                fos.close();
             catch (IOException e) 
                e.printStackTrace();
            
    

【问题讨论】:

查看 saveXMLFile 方法的内容可能会有所帮助。 @Markus ...当然,我已经编辑了问题。 你可以看看Deleting Nodes and Empty Lines in XML Using Java和***.com/questions/7190639/… 【参考方案1】:

首先,解释一下为什么会发生这种情况——这可能有点离题,因为您没有包含用于将 XML 文件加载到 DOM 对象中的代码。

根据 DOM 规范,当您从文件中读取 XML 文档时,标签之间的空格实际上构成了有效的 DOM 节点。因此,XML 解析器将每个这样的空白序列视为一个 DOM 节点(TEXT 类型);

要摆脱它,我可以想到三种方法:

将 XML 与架构相关联,然后在 DocumentBuilderFactory 上使用 setValidating(true)setIgnoringElementContentWhitespace(true)

(注意:setIgnoringElementContentWhitespace 仅在解析器处于验证模式时才有效,这就是为什么您必须使用 setValidating(true)

编写一个 XSL 来处理所有节点,过滤掉只有空格的 TEXT 节点。

使用 Java 代码执行此操作:使用 XPath 查找所有纯空格 TEXT 节点,遍历它们并从其父节点中删除每个节点(使用 getParentNode().removeChild())。这样的事情会做(doc 将是您的 DOM 文档对象):

XPath xp = XPathFactory.newInstance().newXPath();
NodeList nl = (NodeList) xp.evaluate("//text()[normalize-space(.)='']", doc, XPathConstants.NODESET);

for (int i=0; i < nl.getLength(); ++i) 
    Node node = nl.item(i);
    node.getParentNode().removeChild(node);

【讨论】:

我不知道该怎么做 :),但我已将 getXMLFile(...) 代码添加到问题中。 另一种可能性是定义一个 XML 模式来验证文档,然后结合使用 DocumentBuilderFactory 的“setIgnoringElementContentWhitespace”和“setValidating”。给这只猫剥皮的方法很多。 我怎样才能删除

标签中的新行,例如:

细胞色素 P450 还原酶(NADPH-细胞色素 P450 氧化还原酶;EC 1.6.2.4;缩写为 POR或 CPR) 是外源代谢酶细胞色素 P450 (P450) 超家族的关键电子供体。它还在内源性代谢中发挥许多重要作用,将电子传递给一系列受体,包括细胞色素 b5(支持脂肪酸去饱和酶和延长酶活性)、角鲨烯单加氧酶(甾醇生物合成酶

【参考方案2】:

在删除所有旧的“路径”节点后,我可以通过使用此代码来解决此问题:

while( pathsElement.hasChildNodes() )
    pathsElement.removeChild( pathsElement.getFirstChild() );

这将删除 XML 文件中所有生成的空格。

特别感谢 MadProgrammer 对上述有用链接的评论。

【讨论】:

我不会喜欢盲目地删除子节点而不知道它们是什么。至少,我会在这里包含一个测试,看看我真的 am 删除了一个空文本节点(使用 'getNodeType' 和 'getNodeValue')。 @Isaac .. 我同意你的观点,但就我而言,我确信它们都是空的,因为我自己已经删除了它们。相反,如果有东西丢失并且没有被删除,那么我想删除它:) @Brad,请检查我的答案:goo.gl/06Qd9,我解释了如何在不盲目删除所有子节点的情况下删除这些空行,并写了一些关于这种行为的原因。【参考方案3】:

如果您只需要快速“清理”您的 xml,您可以查看 this 之类的内容。 然后你可以有这样的方法:

public static String cleanUp(String xml) 
    final StringReader reader = new StringReader(xml.trim());
    final StringWriter writer = new StringWriter();
    try 
        XmlUtil.prettyFormat(reader, writer);
        return writer.toString();
     catch (IOException e) 
        e.printStackTrace();
    
    return xml.trim();

另外,比较anche检查差异,如果你需要它:XMLUnit

【讨论】:

【参考方案4】:

我遇到了同样的问题,很长一段时间我都不知道,但现在,在布拉德的这个问题和他自己对他自己问题的回答之后,我发现了问题所在。

我必须添加我自己的答案,因为布拉德的答案并不完美,艾萨克怎么说:

我不会喜欢盲目地删除子节点而不知道它们是什么

因此,更好的“解决方案”(引用是因为它更有可能是解决方法)是:

pathsElement.setTextContent("");

这完全删除了无用的空行。这绝对比删除所有子节点要好。布拉德,这应该也适合你。

但是,这是一个结果,而不是原因,我们知道如何消除这个结果,而不是原因。

原因是:当我们调用removeChild() 时,它删除了这个孩子,但是它留下了被删除的孩子的缩进,并且还有换行符。而这个 indent_and_like_break 被当作文本内容处理。

所以,要消除原因,我们应该弄清楚如何消除孩子及其缩进。欢迎来到我的question about this。

【讨论】:

是的,简单得多...假设您确实想在不知道它们是什么的情况下盲目地删除所有子节点。 :-)【参考方案5】:

如果使用 DOM 处理 API(例如 DOM4J),有一种非常简单的方法可以去除空行:

将要保留的文本放入变量中(即text) 使用node.setText("")将节点文本设置为“” 使用node.setText(text)将节点文本设置为text

瞧!没有更多的空行。其他答案很好地描述了 xml 输出中额外的空行实际上是文本类型的额外节点。

这种技术可以用于任何 DOM 解析系统,只要将文本设置函数的名称更改为适合您 API 中的名称,因此表示它的方式稍微抽象一点。

希望这会有所帮助:)

【讨论】:

【参考方案6】:

几点说明: 1)当您操作 XML(删除元素/添加新元素)时,我强烈建议您使用 XSLT(而不是 DOM) 2) 当您通过 XSLT 转换 XML 文档时(就像您在保存方法中所做的那样),将 OutputKeys.INDENT 设置为“no” 3) 对于 xml 的简单后处理(删除空格、cmets 等),您可以使用简单的 SAX2 过滤器

【讨论】:

【参考方案7】:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace(true);

【讨论】:

这不会忽略新生成的 XML 中的空白。测试了这个。【参考方案8】:

我正在使用以下代码:

System.out.println("Start remove textnode");
        i=0;
        while (parentNode.getChildNodes().item(i)!=null) 
            System.out.println(parentNode.getChildNodes().item(i).getNodeName());
            if (parentNode.getChildNodes().item(i).getNodeName().equalsIgnoreCase("#text")) 
                parentNode.removeChild(parentNode.getChildNodes().item(i));
                System.out.println("text node removed");
            
            i=i+1;

        

【讨论】:

【参考方案9】:

当我使用 dom4j 删除一些元素时,我遇到了同样的问题,上面的解决方案在不添加其他一些必需的 jar 的情况下没有用。最后,我找到了一个简单的解决方案,只需要使用 JDK io pakage:

    使用 BufferedReader 读取 xml 文件并过滤空行。
StringBuilder stringBuilder = new StringBuilder();
FileInputStream fis = new FileInputStream(outFile);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String s;
while ((s = br.readLine()) != null) 
  if (s.trim().length() > 0) 
    stringBuilder.append(s).append("\n");
  

    将字符串写入xml文件
OutputStreamWriter osw = new OutputStreamWriter(fou);
BufferedWriter bw = new BufferedWriter(osw);
String str = stringBuilder.toString();
bw.write(str);
bw.flush();
    记得关闭所有流

【讨论】:

【参考方案10】:

在我的例子中,我将它转换为一个字符串,然后只是做了一个正则表达式:

        //save as String
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        tr.transform(new DOMSource(document), result);
        strResult = writer.toString();

        //remove empty lines 
        strResult = strResult.replaceAll("\\n\\s*\\n", "\n");

【讨论】:

是的,当您需要字符串时非常理想。【参考方案11】:

很晚的答案,但也许它仍然对某人有帮助。

我的课堂上有这段代码,文档是在转换后构建的(就像你一样):

TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

将最后一行改为

transformer.setOutputProperty(OutputKeys.INDENT, "no");

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于如何从 XML 文件中删除多余的空行?的主要内容,如果未能解决你的问题,请参考以下文章

dreamweaver中如何清除代码中多余的空行?

如何阻止 IntelliJ IDEA 从 .properties 文件中删除空行?

快速删除段落间多余的空行

Bash:如何删除所有带有扩展名的文件上的所有空行[重复]

Powershell从XML中删除节点并在保存时删除空行

如何从 Python 中的数据中删除多余的逗号