Come rimuovere i nodes di testo di solo spazio bianco da un DOM prima della serializzazione?

Ho un codice Java (5.0) che costruisce un DOM da varie origini dati (memorizzate nella cache), quindi rimuove alcuni nodes elemento non richiesti, quindi serializza il risultato in una stringa XML utilizzando:

// Serialize DOM back into a string Writer out = new StringWriter(); Transformsr tf = TransformsrFactory.newInstance().newTransformsr(); tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); tf.setOutputProperty(OutputKeys.INDENT, "no"); tf.transform(new DOMSource(doc), new StreamResult(out)); return out.toString(); 

Tuttavia, poiché sto rimuovendo diversi nodes di elementi, ho finito con un sacco di spazi bianchi extra nel documento serializzato finale.

C’è un modo semplice per rimuovere / comprimere lo spazio bianco estraneo dal DOM prima (o mentre) è serializzato in una stringa?

Puoi trovare nodes di testo vuoti usando XPath, quindi rimuoverli a livello di programmazione in questo modo:

 XPathFactory xpathFactory = XPathFactory.newInstance(); // XPath to find empty text nodes. XPathExpression xpathExp = xpathFactory.newXPath().compile( "//text()[normalize-space(.) = '']"); NodeList emptyTextNodes = (NodeList) xpathExp.evaluate(doc, XPathConstants.NODESET); // Remove each empty text node from document. for (int i = 0; i < emptyTextNodes.getLength(); i++) { Node emptyTextNode = emptyTextNodes.item(i); emptyTextNode.getParentNode().removeChild(emptyTextNode); } 

Questo approccio potrebbe essere utile se si desidera un maggiore controllo sulla rimozione dei nodes rispetto a quello che si ottiene facilmente con un modello XSL.

Prova a utilizzare il seguente XSL e l’elemento strip-space per serializzare il tuo DOM:

          

http://helpdesk.objects.com.au/java/how-do-i-remove-whitespace-from-an-xml-document

Sotto il codice vengono eliminati i nodes di commento e i nodes di testo con tutti gli spazi vuoti. Se il nodo di testo ha qualche valore, il valore verrà tagliato

 public static void clean(Node node) { NodeList childNodes = node.getChildNodes(); for (int n = childNodes.getLength() - 1; n >= 0; n--) { Node child = childNodes.item(n); short nodeType = child.getNodeType(); if (nodeType == Node.ELEMENT_NODE) clean(child); else if (nodeType == Node.TEXT_NODE) { String trimmedNodeVal = child.getNodeValue().trim(); if (trimmedNodeVal.length() == 0) node.removeChild(child); else child.setNodeValue(trimmedNodeVal); } else if (nodeType == Node.COMMENT_NODE) node.removeChild(child); } } 

Rif: http://www.sitepoint.com/removing-useless-nodes-from-the-dom /

Un altro approccio ansible è rimuovere gli spazi bianchi adiacenti mentre si rimuovono i nodes di destinazione:

 private void removeNodeAndTrailingWhitespace(Node node) { List exiles = new ArrayList(); exiles.add(node); for (Node whitespace = node.getNextSibling(); whitespace != null && whitespace.getNodeType() == Node.TEXT_NODE && whitespace.getTextContent().matches("\\s*"); whitespace = whitespace.getNextSibling()) { exiles.add(whitespace); } for (Node exile: exiles) { exile.getParentNode().removeChild(exile); } } 

Questo ha il vantaggio di mantenere intatto il resto della formattazione esistente.

Il seguente codice funziona:

 public String getSoapXmlFormatted(String pXml) { try { if (pXml != null) { DocumentBuilderFactory tDbFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder tDBuilder; tDBuilder = tDbFactory.newDocumentBuilder(); Document tDoc = tDBuilder.parse(new InputSource( new StringReader(pXml))); removeWhitespaces(tDoc); final DOMImplementationRegistry tRegistry = DOMImplementationRegistry .newInstance(); final DOMImplementationLS tImpl = (DOMImplementationLS) tRegistry .getDOMImplementation("LS"); final LSSerializer tWriter = tImpl.createLSSerializer(); tWriter.getDomConfig().setParameter("format-pretty-print", Boolean.FALSE); tWriter.getDomConfig().setParameter( "element-content-whitespace", Boolean.TRUE); pXml = tWriter.writeToString(tDoc); } } catch (RuntimeException | ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException tE) { tE.printStackTrace(); } return pXml; } public void removeWhitespaces(Node pRootNode) { if (pRootNode != null) { NodeList tList = pRootNode.getChildNodes(); if (tList != null && tList.getLength() > 0) { ArrayList tRemoveNodeList = new ArrayList(); for (int i = 0; i < tList.getLength(); i++) { Node tChildNode = tList.item(i); if (tChildNode.getNodeType() == Node.TEXT_NODE) { if (tChildNode.getTextContent() == null || "".equals(tChildNode.getTextContent().trim())) tRemoveNodeList.add(tChildNode); } else removeWhitespaces(tChildNode); } for (Node tRemoveNode : tRemoveNodeList) { pRootNode.removeChild(tRemoveNode); } } } } 
 transformsr.setOutputProperty(OutputKeys.INDENT, "yes"); 

Ciò manterrà il rientro xml.