11
votes

Comment supprimer des éléments de XML à l'aide de Python

Je suis resté coincé avec XML et Python. La tâche est simple mais je ne pouvais pas le résoudre jusqu'à présent et consacré à cette longue période. Je suis venu ici pour un conseil comment le résoudre avec quelques lignes.

Merci pour toute aide pour traverser l'arbre. J'ai toujours fini avec trop d'éléments trop nombreux. Les éléments peuvent être imbriqués sans limite. Exemple donné n'est qu'un exemple. J'accepterai toute solution, pas difficile à propos de Dom, Minidom, SAX, peu importe. P>

J'ai un fichier XML similaire à celui-ci: p> xxx pré>

Ce dont j'ai besoin - analyser le XML et écrire un nouveau fichier. Le nouveau fichier doit contenir tous les éléments de langue et d'éléments donnés sans attribut lang code>. P>

pour "CS" LANGUE Le fichier de sortie doit conserver ceci: p>

<root>
    <elm>
        <elm>Common content</elm>

        <elm xmlns="http://example.org/ns">
            <elm lang="cs">žluťoučký koníček</elm>
        </elm>

        <elm xml:id="abc123">Common content</elm>

        <elm lang="cs">Content CS</elm>

        <elm lang="cs">
            <elm>Content CS</elm>
            <elm>Content CS</elm>
        </elm>
    </elm>
</root>


2 commentaires

pour "EN" LANGUE Le fichier de sortie doit contenir ceci: Je suppose que vous vouliez dire que la sortie donnée est pour la langue "CS"?


@Larsh: J'ai mis à jour la question pour ajouter des caractères unicode là-bas. Vous avez raison, il devrait être écrit: pour la langue "CS". Va le changer.


3 Réponses :


6
votes

Je ne suis pas sûr de la meilleure façon de supprimer l'attribut lang , mais voici un certain code que l'autre modifie (Python 2.7; pour 2,5 ou 2,6, utilisez getiterator au lieu de iTER ), en supposant que lorsque vous supprimez un élément, vous souhaitez également tout supprimer tout contenus dans cet élément.

Ce code imprime simplement le résultat à la sortie standard (vous pouvez la rediriger comme vous souhaite, bien sûr, ou directement, écrivez-le à un nouveau fichier, et ainsi de suite): xxx

avec la.xml être votre exemple, ceci Écrit xxx


4 commentaires

Merci Alex, travaille génial. Sauf deux choses - Espace de noms et Unicode. S'il y a un attribut XMLNS, par exemple , le nouveau nœud lui-même obtient un xmlns: ns0 = "http: // exemple.org/ns " attribut et tous les nœuds enfants obtiennent un préfixe. Ces préfixes ne sont pas présents dans le fichier source. Ne peut également pas forcer la méthode d'écriture () pour écrire des caractères unicode sous leur forme d'origine. Je vais mettre à jour le fichier exemple.


@Dwich, pour l'écriture, vous pouvez simplement ajouter au écrire appeler un paramètre coding de votre choix. L'esthétique telle que la question de l'espace de noms (que je crois ne change pas la sémantique du XML) sont beaucoup plus titricheuses à gérer, hélas (comme, par exemple, vous avez peut-être remarqué que l'indentation dans la sortie est différente, car Whitpace dans Les éléments enlevés disparaissent également).


Cette chose unicode était mon erreur, j'ai commencé à jouer avec des codecs et même si j'avais utilisé coding = 'utf-8' , il n'a pas fonctionné (COZ d'ouverture de l'ouverture incorrecte). Merci de votre réponse, je choisirai une solution ~ tsutbu alors que son code n'a pas de problèmes avec la chose d'espace de noms. Les deux réponses sont correctes. Merci les gars!


@Dwich, je suis d'accord avec vous - @ La réponse d'@ Unutbu est meilleure (si vous pouvez utiliser des packages tiers tels que LXML), entre autres parce que vous supprimez l'attribut, comme vous l'avez idéalement souhaité, tandis que le mien, comme je l'ai mentionné, .



12
votes

en utilisant lxml : xxx

rendements xxx


2 commentaires

Merci beaucoup. Impossible d'installer LXML sur mon WinXP, problème avec Compiler. Va le donner un essai plus tard.


Travaux! Merci! Vous avez sauvé ma nuit :) Je vous remercie tous les deux, les deux solutions sont bonnes.



2
votes

Mise à jour du code de @Alex Martelli pour supprimer un bogue où la liste des éléments est mise à jour en place. La solution ci-dessus donnera une mauvaise réponse si l'entrée est un peu plus complexe.

import sys
from xml.etree import cElementTree as et

def picklang(path, lang='en'):
    tr = et.parse(path)
    for element in tr.iter():
        for subelement in element[:]:
            la = subelement.get('lang')

            if la is not None and la != lang:
                element.remove(subelement)
    return tr

if __name__ == '__main__':
    tr = picklang('la.xml')
    tr.write(sys.stdout)
    print


0 commentaires