nodos manejo leer extraer datos archivos java xml dom whitespace

manejo - leer nodos xml java



¿Cómo eliminar los nodos de texto de solo espacios en blanco de un DOM antes de la serialización? (6)

El siguiente código elimina los nodos de comentario y los nodos de texto con todos los espacios vacíos. Si el nodo de texto tiene algún valor, el valor será recortado

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

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

Tengo un código Java (5.0) que construye un DOM a partir de varias fuentes de datos (en caché), luego elimina ciertos nodos de elementos que no son necesarios y luego serializa el resultado en una cadena XML utilizando:

// Serialize DOM back into a string Writer out = new StringWriter(); Transformer tf = TransformerFactory.newInstance().newTransformer(); 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();

Sin embargo, ya que estoy eliminando varios nodos de elementos, termino con una gran cantidad de espacios en blanco adicionales en el documento final serializado.

¿Hay una forma sencilla de eliminar / contraer el espacio en blanco extraño del DOM antes (o mientras) se serializa en una cadena?


El siguiente código funciona:

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<Node> tRemoveNodeList = new ArrayList<Node>(); 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); } } } }


Intente usar el siguiente XSL y el elemento de strip-space separación para serializar su DOM:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>

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


Otro posible enfoque es eliminar los espacios en blanco vecinos al mismo tiempo que elimina los nodos de destino:

private void removeNodeAndTrailingWhitespace(Node node) { List<Node> exiles = new ArrayList<Node>(); 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); } }

Esto tiene la ventaja de mantener el resto del formato existente intacto.


Puede encontrar nodos de texto vacíos usando XPath, luego eliminarlos programáticamente de la siguiente manera:

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

Este enfoque podría ser útil si desea más control sobre la eliminación de nodos que el que se logra fácilmente con una plantilla XSL.


transformer.setOutputProperty(OutputKeys.INDENT, "yes");

Esto mantendrá la sangría xml.