如何从 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)
)
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 文件中删除多余的空行?的主要内容,如果未能解决你的问题,请参考以下文章