2012-10-01 33 views
10

En resumen; Tengo muchas líneas vacías generadas en un archivo XML, y estoy buscando una manera de eliminarlas como una forma de inclinar el archivo. Cómo puedo hacer eso ?¿Cómo eliminar las líneas adicionales vacías del archivo XML?

Para una explicación detallada; Actualmente tengo este archivo XML:

<recent> 
    <paths> 
    <path>path1</path> 
    <path>path2</path> 
    <path>path3</path> 
    <path>path4</path> 
    </paths> 
</recent> 

y utilizo este código Java para eliminar todas las etiquetas, y añadir otros nuevos en su lugar:

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

Después de ejecutar este método varias veces me sale un XML archivo con resultados correctos, pero con muchas líneas vacías después de la etiqueta de "caminos" y antes de la primera etiqueta "camino", como este:

<recent> 
    <paths> 





    <path>path5</path> 
    <path>path6</path> 
    <path>path7</path> 
    </paths> 
</recent> 

Cualquier persona sabe cómo solucionar esto?

------------------------------------------- Editar: Agregue el código 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(); 
      } 
    } 
} 
+0

Podría ser útil para ver el contenido de su método saveXMLFile. – Markus

+0

@Markus ... Claro, he editado la pregunta. – Brad

+1

Puedes echar un vistazo a [Eliminar nodos y líneas vacías en XML usando Java] (http://techxplorer.com/2010/05/24/deleting-nodes-and-empty-lines-in-xml-using-java /) y http://stackoverflow.com/questions/7190639/remove-all-blank-spaces-and-empty-lines – MadProgrammer

Respuesta

3

yo era capaz de solucionar este problema mediante el uso de este código después de la eliminación de toda la antigua "ruta" nodos:

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

Esto eliminará todos los espacios vacíos generados en el archivo XML.

Gracias especiales a MadProgrammer por comentar con el útil enlace mencionado anteriormente.

+0

No sería un gran fanático de eliminar ciegamente los nodos secundarios sin saber cuáles son. Por lo menos, incluiría una prueba aquí para ver que realmente * estoy * eliminando un nodo de texto vacío (usando 'getNodeType' y 'getNodeValue'). – Isaac

+0

@Isaac .. Estoy de acuerdo contigo, pero en mi caso, estoy seguro de que están todos vacíos, porque ya los borré yo. Por el contrario, si falta algo y no se elimina, entonces quiero eliminarlo :) – Brad

+0

@Brad, por favor revisa mi respuesta: http://goo.gl/06Qd9, expliqué cómo eliminar estas líneas en blanco sin ceguera eliminando todos los nodos secundarios, y escribió algo sobre la causa de tal comportamiento. –

0

par de comentarios: 1) Cuando su están manipulando XML (eliminación de elementos/añadir uno nuevo) Le aconsejo encarecidamente que use XSLT (y no DOM) 2) Cuando TRANFORM un documento XML XSLT (como lo hace en su método de guardar), establezca las OutputKeys.INDENT en "no" 3) Para el procesamiento posterior simple de su xml (eliminación de espacios en blanco, comentarios, etc.) puede usar un filtro SAX2 simple

1

Puede mirar algo como this si solo necesita "limpiar" su xml rápidamente. entonces usted podría tener un método como:

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

Además, para comparar anche diferencias de verificación, si lo necesita: XMLUnit

14

En primer lugar, una explicación de por qué sucede esto - lo que podría ser un poco desde no incluyó el código que se utiliza para cargar el archivo XML en un objeto DOM.

Cuando lee un documento XML de un archivo, los espacios en blanco entre etiquetas realmente constituyen nodos DOM válidos, de acuerdo con la especificación DOM. Por lo tanto, el analizador XML trata cada secuencia de espacios en blanco como nodos DOM (de tipo "TEXTO");

Para deshacerse de él, hay tres enfoques que se me ocurren:

  • Asociado del XML con un esquema, y ​​luego usar setValidating(true) junto con setIgnoringElementContentWhitespace(true) en el DocumentBuilderFactory.

    (Nota: setIgnoringElementContentWhitespace sólo funcionará si el analizador está en modo de validación, por lo que debe utilizar setValidating(true))

  • Escribir un XSL para procesar todos los nodos, el filtrado de los nodos de texto por espacios en blanco solamente.
  • Utilice el código de Java para hacer esto: use XPath para buscar todos los nodos de TEXTO de solo espacios en blanco, repítalo y elimine cada uno de sus elementos principales (usando getParentNode().removeChild()).Para hacer esto en código Java, algo como esto haría (doc sería su documento objeto 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); 
    } 
    
+0

No sé cómo hacer eso :), pero he agregado el getXMLFile (...) código a la pregunta. – Brad

+0

OK, editaré mi respuesta para incluir el código de Java requerido. – Isaac

+0

Otra posibilidad sería definir un esquema XML para validar el documento y luego usar "setIgnoringElementContentWhitespace" de DocumentBuilderFactory junto con "setValidating". Muchas formas de despellejar a este gato. – Isaac

1

Me enfrenté al mismo problema, y ​​no tenía idea por mucho tiempo, pero ahora, después de la pregunta de Brad y su propia respuesta a su propia pregunta, descubrí dónde está el problema.

Tengo que añadir mi propia respuesta, porque uno de Brad no es realmente perfecto, cómo Isaac dijo:

no habría un gran fan de la eliminación de nodos secundarios ciegamente sin saber lo que son

Por lo tanto, mejor "solución" (citado debido a que es más probable solución) es:

pathsElement.setTextContent(""); 

Esto elimina por completo las líneas en blanco inútiles. Definitivamente es mejor que eliminar todos los nodos secundarios. Brad, esto debería funcionar para ti también.

Pero, esto es un efecto, no la causa, y tenemos cómo eliminar este efecto, no la causa.

Causa es: cuando llamamos removeChild(), elimina este elemento secundario, pero deja la sangría del elemento secundario eliminado y también el salto de línea. Y este indent_and_like_break se trata como un contenido de texto.

Por lo tanto, para eliminar la causa, debemos averiguar cómo eliminar el niño y su sangría. Bienvenido a mi question about this.

+0

Sí, mucho más simple ... suponiendo que QUIERES eliminar ciegamente todos los nodos secundarios sin saber cuáles son. :-) –

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

Esto no ignorará el espacio en blanco en el XML generado recientemente. Se aprueba esto. – NeverGiveUp161

0

Hay una forma muy sencilla de deshacerse de las líneas vacías si se utiliza un manejo API (por ejemplo DOM4J) DOM:

  • lugar el texto que desea guardar en una variable (es decir, text)
  • establecer el texto nodo a "" usar node.setText("")
  • establecer el texto nodo a text usando node.setText(text)

et voila! no hay más líneas vacías Las otras respuestas delinean muy bien cómo las líneas vacías adicionales en la salida xml son realmente nodos adicionales de tipo texto.

Esta técnica se puede utilizar con cualquier sistema de análisis DOM, siempre que el nombre de la función de configuración de texto se modifique para que coincida con el de su API, de ahí la manera de representarlo de forma un poco más abstracta.

Espero que esto ayude :)

1

estoy usando continuación Código:

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; 

     } 
+0

¡Gracias, funciona perfectamente! – Flyout

Cuestiones relacionadas