64 votes

Enregistrement de fichiers XML à l'aide d'ElementTree

J'essaie de développer un code Python (3.2) simple pour lire des fichiers XML, effectuer quelques opérations de lecture et d'écriture. corrections et les remettre en mémoire. Cependant, au cours de l'étape de stockage, ElementTree ajoute cette nomenclature d'espace de noms. Par exemple :

<ns0:trk>
  <ns0:name>ACTIVE LOG</ns0:name>
<ns0:trkseg>
<ns0:trkpt lat="38.5" lon="-120.2">
  <ns0:ele>6.385864</ns0:ele>
  <ns0:time>2011-12-10T17:46:30Z</ns0:time>
</ns0:trkpt>
<ns0:trkpt lat="40.7" lon="-120.95">
  <ns0:ele>5.905273</ns0:ele>
  <ns0:time>2011-12-10T17:46:51Z</ns0:time>
</ns0:trkpt>
<ns0:trkpt lat="43.252" lon="-126.453">
  <ns0:ele>7.347168</ns0:ele>
  <ns0:time>2011-12-10T17:52:28Z</ns0:time>
</ns0:trkpt>
</ns0:trkseg>
</ns0:trk>

L'extrait de code est ci-dessous :

def parse_gpx_data(gpxdata, tzname=None, npoints=None, filter_window=None,
                   output_file_name=None):
        ET = load_xml_library();

    def find_trksegs_or_route(etree, ns):
        trksegs=etree.findall('.//'+ns+'trkseg')
        if trksegs:
            return trksegs, "trkpt"
        else: # try to display route if track is missing
            rte=etree.findall('.//'+ns+'rte')
            return rte, "rtept"

    # try GPX10 namespace first
    try:
        element = ET.XML(gpxdata)
    except ET.ParseError as v:
        row, column = v.position
        print ("error on row %d, column %d:%d" % row, column, v)

    print ("%s" % ET.tostring(element))
    trksegs,pttag=find_trksegs_or_route(element, GPX10)
    NS=GPX10
    if not trksegs: # try GPX11 namespace otherwise
        trksegs,pttag=find_trksegs_or_route(element, GPX11)
        NS=GPX11
    if not trksegs: # try without any namespace
        trksegs,pttag=find_trksegs_or_route(element, "")
        NS=""

    # Store the results if requested
    if output_file_name:
        ET.register_namespace('', GPX11)
        ET.register_namespace('', GPX10)
        ET.ElementTree(element).write(output_file_name, xml_declaration=True)

    return;

J'ai essayé d'utiliser le register_namespace mais sans résultat positif. Y a-t-il des changements spécifiques pour cette version d'ElementTree 1.3 ?

1 votes

Dites-moi si j'ai bien compris votre question, vous aimeriez avoir <trk> au lieu de <ns0:trk> et ainsi de suite ?

1 votes

Correct. J'aimerais avoir <trk> au lieu de <ns0:trk> et ainsi de suite.

0 votes

Ce n'est pas une vraie solution, mais comme il semble que vous chargez une chaîne de caractères, avez-vous essayé de supprimer l'espace de nom avec un regexp ? Après cela, si vous chargez et sauvegardez sans tout, tout devrait être correct.

92voto

ilya1725 Points 494

Afin d'éviter le ns0 le préfixe de l'espace de nom par défaut doit être défini avant lire les données XML.

ET.register_namespace('', "http://www.topografix.com/GPX/1/1")
ET.register_namespace('', "http://www.topografix.com/GPX/1/0")

2 votes

On dirait que ce n'était pas avant. Je suis capable de lire le fichier XML et d'obtenir l'espace de noms et seulement après cela de définir register_namespace. tree = ET.parse(str(udx_path)) Root = tree.getroot() ns = { # Extraire l'espace de noms de l'élément Root 'udx' : Root.tag[1:Root.tag.index('}')] } ET.register_namespace('', Root.tag[1:Root.tag.index('}')])

1 votes

Ce n'est pas une façon complète de préserver la différence entre la chaîne de l'ElementTree analysée et celle de la sortie (si l'on utilise ElementTree.tostring(Root)). singingsingh est complet.

49voto

singingsingh Points 135

Vous devez enregistrer tous vos espaces de noms avant d'analyser le fichier xml.

Par exemple : Si vous avez votre entrée xml comme ceci et Capacités est la racine de votre arbre d'éléments.

<Capabilities xmlns="http://www.opengis.net/wmts/1.0"
    xmlns:ows="http://www.opengis.net/ows/1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:gml="http://www.opengis.net/gml"
    xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd"
    version="1.0.0">

Ensuite, vous devez enregistrer tous les espaces de noms, c'est-à-dire les attributs présents dans l'élément xmlns comme ça :

ET.register_namespace('', "http://www.opengis.net/wmts/1.0")
ET.register_namespace('ows', "http://www.opengis.net/ows/1.1")
ET.register_namespace('xlink', "http://www.w3.org/1999/xlink")
ET.register_namespace('xsi', "http://www.w3.org/2001/XMLSchema-instance")
ET.register_namespace('gml', "http://www.opengis.net/gml")

0 votes

Cette réponse est la réponse complète.

2voto

Si vous essayez d'imprimer la Racine, vous verrez quelque chose comme ceci : http://www.host.domain/path/to/your/xml/namespace}RootTag' at 0x0000000000558DB8>

Donc, pour éviter le ns0 vous devez modifier l'espace de noms par défaut avant d'analyser les données XML comme ci-dessous :

ET.register_namespace('', "http://www.host.domain/path/to/your/xml/namespace")

1voto

Rik Poggi Points 10195

Il semble que vous deviez déclarer votre espace de nom, ce qui signifie que vous devez changer la première ligne de votre xml de :

<ns0:trk>

à quelque chose comme :

<ns0:trk xmlns:ns0="uri:">

Une fois fait, vous ne recevrez plus ParseError: for unbound prefix: ... et :

elem.tag = elem.tag[(len('{uri:}'):]

supprimera l'espace de nom.

0 votes

Salut Rik. L'exemple XML que j'ai montré est le sortie . Le XML d'entrée, qui est bien analysé, n'a pas le préfixe "ns0 :". Il s'agit simplement d'un code GPX standard.

0 votes

Si la ligne element = ET.XML(gpxdata) vous donne un élément avec ns0 alors le "problème" est dans les gpxdata, dans ce cas vous avez deux options : "réparer" les gpxdata ou trouver pourquoi l'analyseur standard fait cela et en construire un nouveau pour les gpxdata. ET.XML .

0 votes

Le gpxdata original n'a pas de ns0 entrées. Cependant, votre conseil, Rik, m'a en quelque sorte conduit à la solution. En gros, le ET.register_namespace('', GPX11) ET.register_namespace('', GPX10) doit être fait avant la lecture, c'est-à-dire que ET.XML .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X