Question Comment supprimer les lignes vides supplémentaires du fichier XML?


En bref; J'ai beaucoup de lignes vides générées dans un fichier XML, et je cherche un moyen de les supprimer comme un moyen d'appuyer le fichier. Comment puis je faire ça ?

Pour une explication détaillée; J'ai actuellement ce fichier XML:

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

Et j'utilise ce code Java pour supprimer tous les tags et en ajouter de nouveaux à la place:

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

Après avoir exécuté cette méthode un certain nombre de fois, je reçois un fichier XML avec des résultats corrects, mais avec de nombreuses lignes vides après la balise "chemins" et avant la première balise "chemin", comme ceci:

<recent>
  <paths>





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

Quelqu'un sait comment résoudre ce problème?

------------------------------------------- Edit: Ajoutez le fichier getXMLFile (. ..), code 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();
            }
    }
}

10
2017-10-01 08:19


origine


Réponses:


Tout d'abord, une explication de la raison pour laquelle cela se produit - ce qui peut être un peu effacé puisque vous n'avez pas inclus le code utilisé pour charger le fichier XML dans un objet DOM.

Lorsque vous lisez un document XML à partir d'un fichier, les espaces blancs entre les balises constituent en réalité des nœuds DOM valides, conformément à la spécification DOM. Par conséquent, l'analyseur XML traite chaque séquence d'espaces blancs comme des noeuds DOM (de type "TEXT");

Pour s'en débarrasser, il y a trois approches possibles:

  • Associez le XML à un schéma, puis utilisez setValidating(true) de même que setIgnoringElementContentWhitespace(true) sur le DocumentBuilderFactory.

    (Remarque: setIgnoringElementContentWhitespace ne fonctionnera que si l’analyseur est en mode validation, c’est pourquoi vous devez utiliser setValidating(true))

  • Écrivez un fichier XSL pour traiter tous les nœuds, en filtrant les nœuds TEXTE contenant uniquement des espaces.
  • Pour ce faire, utilisez le code Java: utilisez XPath pour rechercher tous les noeuds TEXTE contenant uniquement des espaces, effectuez une itération et supprimez chacun d'eux de son parent (en utilisant getParentNode().removeChild()). Pour faire cela en code Java, quelque chose comme ça ferait (doc serait votre objet de document 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);
    }
    

14
2017-10-01 08:57



J'ai pu résoudre ce problème en utilisant ce code après avoir supprimé tous les anciens nœuds "path":

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

Cela supprimera tous les espaces vides générés dans le fichier XML.

Merci spécial à MadProgrammer pour commenter avec le lien utile mentionné ci-dessus.


3
2017-10-01 13:12



Vous pourriez regarder quelque chose comme ce si vous avez seulement besoin de "nettoyer" votre xml rapidement. Ensuite, vous pourriez avoir une méthode comme:

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

Aussi, pour comparer les différences de vérification d’angoisse, si vous en avez besoin: XMLUnit


1
2017-10-01 08:45



J'ai rencontré le même problème, et je n'en avais aucune idée depuis longtemps, mais maintenant, après la question de Brad et sa propre réponse à sa propre question, j'ai compris où était le problème.

Je dois ajouter ma propre réponse, car celle de Brad n'est pas vraiment parfaite, comment Isaac a dit:

Je ne serais pas un grand fan de supprimer aveuglément les nœuds enfants sans savoir ce qu'ils sont

Donc, une meilleure "solution" (citée parce que la solution est plus probable) est:

pathsElement.setTextContent("");

Cela supprime complètement les lignes vierges inutiles. C'est nettement mieux que de supprimer tous les nœuds enfants. Brad, ça devrait marcher pour toi aussi.

Mais, c'est un effet, pas la cause, et nous avons comment supprimer cet effet, pas la cause.

La cause est: quand on appelle removeChild(), il enlève cet enfant, mais il laisse en retrait de l'enfant enlevé, et le saut de ligne aussi. Et ce indent_and_like_break est traité comme un contenu textuel.

Donc, pour supprimer la cause, nous devrions trouver comment enlever l'enfant et son retrait. Bienvenue à mon question à ce sujet.


1
2018-01-10 09:57



J'utilise le code ci-dessous:

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;

        }

1
2017-07-11 06:48



Quelques remarques: 1) Lorsque vous manipulez du XML (en supprimant des éléments / en en ajoutant un nouveau), je vous conseille fortement d'utiliser XSLT (et non DOM) 2) Lorsque vous transformez un document XML par XSLT (comme vous le faites dans votre méthode save), définissez le paramètre OutputKeys.INDENT sur "no" 3) Pour un post-traitement simple de votre xml (suppression des espaces blancs, des commentaires, etc.), vous pouvez utiliser un simple filtre SAX2


0
2017-10-01 08:41



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

0
2017-11-05 18:15



Il existe un moyen très simple de se débarrasser des lignes vides si vous utilisez une API de gestion DOM (par exemple DOM4J):

  • placez le texte que vous souhaitez conserver dans une variable (c.-à-d. text)
  • définir le texte du noeud sur "" en utilisant node.setText("")
  • définir le texte du noeud sur text en utilisant node.setText(text)

et voilà! il n'y a plus de lignes vides. Les autres réponses définissent très bien comment les lignes vides supplémentaires dans la sortie xml sont en réalité des nœuds supplémentaires de type texte.

Cette technique peut être utilisée avec n'importe quel système d'analyse de DOM, à condition que le nom de la fonction de définition de texte soit modifié pour correspondre à celui de votre API, d'où la manière de la représenter de manière un peu plus abstraite.

J'espère que cela t'aides:)


0
2018-05-09 10:00