web-dev-qa-db-fra.com

Enregistrement de fichiers XML à l'aide d'ElementTree

J'essaie de développer un simple code Python (3.2) pour lire les fichiers XML, faire quelques corrections et les stocker. Cependant, lors de l'étape de stockage, ElementTree ajoute ceci nomenclature de l'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?

40
ilya1725

Afin d'éviter le ns0 préfixe l'espace de noms par défaut doit être défini avant lecture des données XML.

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

Vous devez enregistrer tous vos espaces de noms.

Par exemple: si vous avez votre XML d'entrée comme celui-ci

<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 avec xmlns comme ceci:

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")
23
singingsingh

Cette réponse m'a vraiment aidé à éviter le problème ns0. Je convertis GPX de GPaws (quand cela fonctionne) en KML (pour Google maps) et mon code ne fonctionnait pas jusqu'à ce que je définisse l'espace de noms par défaut comme ceci ET.register_namespace("","http://www.opengis.net/kml/2.2")

1
user3604332

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

<ns0:trk>

à quelque chose comme:

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

Une fois cela fait, vous n'obtiendrez plus ParseError: for unbound prefix: ..., et:

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

supprimera l'espace de noms.

0
Rik Poggi