以递归方式从XML中删除空节点

我想从XML元素中删除空节点。 这个xml是从供应商生成的,我没有xml生成的控制权。 但由于XML几乎没有空节点,我需要递归删除这些空节点。

这个xml来自OMElement,我使用[XMLUtils] [1] Sample XML从这个对象中获取一个Element

    something something       something else           

由于D21是一个空节点,我想删除D21,因为现在D2是一个空节点,我想删除D2,但由于D有D1,我不想删除D.

同样,我有可能得到

       

现在,因为C是空的,我想删除C然后B,然后最终删除节点A.我试图在Node中使用removeChild()方法执行此操作

但到目前为止,我无法递归删除它们。 有什么建议可以递归删除它们吗?

我递归地尝试获取节点和节点长度。 但节点长度没有帮助

 if(childNode.getChildNodes().getLength() == 0 ){ childNode.getParentNode().removeChild(childNode); } 

问候
Dheeraj Joshi

这样做,只需创建一个“深入”的递归函数,然后在“备份树”的路上删除空节点,这将具有删除D21和D2的效果。

 public static void main(String[] args) throws Exception { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); String input = "somethingsomethingsomething else"; Document document = builder.parse(new InputSource(new StringReader( input))); removeNodes(document); Transformer transformer = TransformerFactory.newInstance() .newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); StreamResult result = new StreamResult(new StringWriter()); transformer.transform(new DOMSource(document), result); System.out.println(result.getWriter().toString()); } public static void removeNodes(Node node) { NodeList list = node.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { removeNodes(list.item(i)); } boolean emptyElement = node.getNodeType() == Node.ELEMENT_NODE && node.getChildNodes().getLength() == 0; boolean emptyText = node.getNodeType() == Node.TEXT_NODE && node.getNodeValue().trim().isEmpty(); if (emptyElement || emptyText) { node.getParentNode().removeChild(node); } } 

产量

     something something       something else       

我没有足够的代表来评论@Adam的解决方案,但我遇到了一个问题,即在删除节点后,该节点的最后一个兄弟被移动到索引零,导致它不能完全删除空元素。 修复是使用一个列表来保存我们想要递归调用删除的所有节点。

此外,还有一个错误删除了具有属性的空元素。

解决这两个问题:

 public static void removeEmptyNodes(Node node) { NodeList list = node.getChildNodes(); List nodesToRecursivelyCall = new LinkedList(); for (int i = 0; i < list.getLength(); i++) { nodesToRecursivelyCall.add(list.item(i)); } for(Node tempNode : nodesToRecursivelyCall) { removeEmptyNodes(tempNode); } boolean emptyElement = node.getNodeType() == Node.ELEMENT_NODE && node.getChildNodes().getLength() == 0; boolean emptyText = node.getNodeType() == Node.TEXT_NODE && node.getNodeValue().trim().isEmpty(); if (emptyElement || emptyText) { if(!node.hasAttributes()) { node.getParentNode().removeChild(node); } } } 

在DOM的顶级元素上使用getTextContent() 。 如果方法返回空字符串或null,则可以删除此节点,因为此节点和所有子节点都为空。 如果方法getTextContent()不返回空字符串,则在当前节点的每个子节点上调用getTextContent ,依此类推。
见文档 。

 public class RemoveEmprtElement { public static void main(String[] args) { ReadFile readFile =new ReadFile(); String strXml=readFile.readFileFromPath(new File("sampleXml4.xml")); RemoveEmprtElement elementEmprtElement=new RemoveEmprtElement(); DocumentBuilder dBuilder = null; Document doc = null; try { dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = dBuilder.parse(new ByteArrayInputStream(strXml.getBytes())); elementEmprtElement.getEmptyNodes(doc); TransformerFactory tf = TransformerFactory.newInstance(); Transformer trans = tf.newTransformer(); StreamResult result = new StreamResult(new StringWriter()); trans.transform(new DOMSource(doc), result); System.out.println(result.getWriter().toString()); }catch(Exception e) { e.printStackTrace(); } } private void getEmptyNodes(Document doc){ try { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile("//*[not(*)]"); Object resultNS = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) resultNS; for(int i =0 ; i < nodes.getLength() ; i++){ Node node = nodes.item(i); boolean emptyElement = node.getNodeType() == Node.ELEMENT_NODE && node.getChildNodes().getLength() == 0; boolean emptyText = node.getNodeType() == Node.TEXT_NODE && node.getNodeValue().trim().isEmpty(); if (emptyElement || emptyText) { xmlNodeRemove(doc,findPath(node)); getEmptyNodes(doc); } } }catch(Exception e) { e.printStackTrace(); } } private void xmlNodeRemove(Document doc,String xmlNodeLocation){ try { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile(xmlNodeLocation); Object resultNS = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) resultNS; Node node =nodes.item(0); if(node!=null && node.getParentNode()!=null && node.getParentNode().hasChildNodes()){ node.getParentNode().removeChild(node); } }catch(Exception e) { e.printStackTrace(); } } private String findPath(Node n) { String path=""; if(n==null){ return path; }else if(n.getNodeName().equals("#document")){ return ""; } else{ path=n.getNodeName(); path=findPath(n.getParentNode())+"/"+path; } return path; } } 

只需使用字符串:

  Pattern emptyValueTag = Pattern.compile("\\s*<\\w+/>"); Pattern emptyTagMultiLine = Pattern.compile("\\s*<\\w+>\n*\\s*"); xml = emptyValueTag.matcher(xml).replaceAll(""); while (xml.length() != (xml = emptyTagMultiLine.matcher(xml).replaceAll("")).length()) { } return xml;