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

简而言之; 我在XML文件中生成了许多空行,我正在寻找一种方法来删除它们作为一种倾斜文件的方式。 我怎样才能做到这一点 ?

详细说明; 我目前有这个XML文件:

  path1 path2 path3 path4   

我使用此Java代码删除所有标记,并添加新标记:

 public void savePaths( String recentFilePath ) { ArrayList newPaths = getNewRecentPaths(); Document recentDomObject = getXMLFile( recentFilePath ); // Get the  element. NodeList pathNodes = recentDomObject.getElementsByTagName( "path" ); // Get all  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  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”标记之前有许多空行,如下所示:

   path5 path6 path7   

谁知道如何解决这个问题?

——————————————-编辑:添加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(); } } } 

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

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

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

  • 将XML与模式相关联,然后在DocumentBuilderFactory上使用setIgnoringElementContentWhitespace(true)setIgnoringElementContentWhitespace(true)

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

  • 编写一个XSL来处理所有节点,过滤掉仅空白的TEXT节点。
  • 使用Java代码执行此操作:使用XPath查找所有仅空白的TEXT节点,迭代它们并从其父节点中删除每个节点(使用getParentNode().removeChild() )。 要在Java代码中执行此操作,这样的事情( 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); } 

我删除了所有旧的“路径”节点后,通过使用此代码解决了这个问题:

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

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

特别感谢MadProgrammer使用上面提到的有用链接进行评论。

如果你只需要快速“清理”你的xml,你可以看看这样的东西。 然后你可以有一个像这样的方法:

 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 check差异,如果需要: XMLUnit

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

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

在不知道它们是什么的情况下,我不会盲目地删除子节点

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

 pathsElement.setTextContent(""); 

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

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

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

因此,要消除原因,我们应该弄清楚如何删除子及其缩进 。 欢迎提出我的问题 。

我使用下面的代码:

 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; } 

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

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

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

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

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

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

希望这可以帮助:)