2012-01-24 69 views
30

Estoy tratando de desarrollar código simple de Python (3.2) para leer archivos XML, hacer algunas correcciones y almacenarlas de nuevo. Sin embargo, durante el paso de almacenamiento, ElementTree agrega esta nomenclatura de espacio de nombres. Por ejemplo:Guardar archivos XML usando ElementTree

<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> 

El fragmento de código es el siguiente:

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; 

He intentado usar el register_namespace, pero sin ningún resultado positivo. ¿Hay algún cambio específico para esta versión de ElementTree 1.3?

+0

Dime si he entendido su pregunta, ¿desea tener '' en lugar de '' y así sucesivamente? –

+0

Correcto. Me gustaría tener en lugar de y así sucesivamente. – ilya1725

+0

Esta no es una solución real, pero dado que parece que cargas una cadena, ¿has intentado eliminar el espacio de nombres con algunas expresiones regulares? Después de eso, si carga y guarda sin todo debería estar bien. –

Respuesta

55

Para evitar el prefijo ns0, el espacio de nombre predeterminado debe establecerse antes de leyendo los datos XML.

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

Parece que no antes. Puedo leer el archivo XML y obtener el espacio de nombres y solo después de eso establecer register_namespace. árbol = ET.parse (str (udx_path)) root = tree.getroot() ns = {# extracto de espacio de nombres del elemento raíz 'UDX': root.tag [1: root.tag.index (' } ')] } ET.register_namespace (' ', root.tag [1: root.tag.index ('} ')]) – likern

0

Parece que usted tiene que declarar el espacio de nombres, lo que significa que tiene que cambiar la primera línea de su XML desde:

<ns0:trk> 

a algo como:

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

hizo una vez que se ya no se quedarán ParseError: for unbound prefix: ..., y:

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

eliminará el namesp as.

+0

Hola Rik. El ejemplo XML que mostré es _output_. El XML de entrada, que analiza bien, no tiene el prefijo 'ns0:'. Es solo un código GPX estándar. – ilya1725

+0

Si la línea 'element = ET.XML (gpxdata)' le da un elemento con 'ns0' entonces el" problema "está en gpxdata, en cuyo caso debe tener las siguientes opciones:" arreglar "gpxdata o averiguar por qué el estándar el analizador hace eso y crea uno nuevo para ['ET.XML'] (http://docs.python.org/py3k/library/xml.etree.elementtree.html#xml.etree.ElementTree.XML). –

+0

El gpxdata original no tiene ninguna entrada 'ns0'. Sin embargo, su pista, Rik, me llevó a la solución. Básicamente, el 'ET.register_namespace ('', GPX11)' 'ET.register_namespace ('', GPX10)' se debe hacer antes de leer, es decir, 'ET.XML'. – ilya1725

1

Esta respuesta realmente me ayudó a evitar el problema ns0. Estoy convirtiendo GPX de GPaws (cuando funciona) a KML (para los mapas de Google) y mi código no estaba trabajando hasta que me puse el nombre por defecto como éste ET.register_namespace(""," http://www.opengis.net/kml/2.2 ")

6

Es necesario registrar todos los espacios de nombres.

Por ejemplo: Si usted tiene su entrada XML como esto

<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"> 

entonces usted tiene que registrar a todos los espacios de nombres es decir, los atributos presentes con xmlns así:

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") 
Cuestiones relacionadas