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

时间:2012-10-01 08:19:46

标签: java xml carriage-return code-cleanup

总之;我在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文件,但在“paths”标记之后和第一个“path”标记之前有许多空行,如下所示:

<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/xslt}indent-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();
            }
    }
}

10 个答案:

答案 0 :(得分:20)

首先,解释为什么会发生这种情况 - 由于您没有包含用于将XML文件加载到DOM对象的代码,因此可能会有点失误。

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

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

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

    (注意: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);
    }
    

答案 1 :(得分:3)

我能够在删除所有旧的“路径”节点后使用此代码解决此问题:

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

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

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

答案 2 :(得分:1)

如果您只需要快速“清理”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();
}

此外,如果您需要,请比较安检检查差异:XMLUnit

答案 3 :(得分:1)

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

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

  

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

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

pathsElement.setTextContent("");

这完全消除了无用的空白行。它肯定比删除所有子节点更好。布拉德,这也适合你。

但是,这是一种效果,而不是原因,我们得到了如何去除这种效果,而不是原因。

原因是:当我们调用removeChild()时,它会删除此子项,但会删除子项的缩进,并且也会断行。此indent_and_like_break被视为文本内容。

因此,为了消除原因,我们应该找出如何删除子项及其缩进。欢迎来到我的question about this

答案 4 :(得分:1)

我正在使用以下代码:

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;

        }

答案 5 :(得分:0)

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

答案 6 :(得分:0)

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace(true);

答案 7 :(得分:0)

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

  • 将您要保留的文字放在变量中(例如 text
  • 将节点文本设置为&#34;&#34;使用node.setText("")
  • 使用text
  • 将节点文本设置为 node.setText(text)
瞧,瞧!没有空行。其他答案非常清楚地描述了xml输出中的额外空行实际上是文本类型的额外节点。

此技术可以与任何DOM解析系统一起使用,只要文本设置功能的名称更改为适合API中的名称,因此可以稍微抽象地表示它。

希望这有帮助:)

答案 8 :(得分:0)

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

  1. 使用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");
  }
}
  1. 将字符串写入xml文件
OutputStreamWriter osw = new OutputStreamWriter(fou);
BufferedWriter bw = new BufferedWriter(osw);
String str = stringBuilder.toString();
bw.write(str);
bw.flush();
  1. 记住关闭所有流

答案 9 :(得分:0)

就我而言,我将其转换为字符串,然后只做了一个正则表达式:

        //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");