web-dev-qa-db-ja.com

ElementTreeを使用してXMLファイルを保存する

私は単純なPython(3.2)コードを開発してXMLファイルを読み取り、いくつかの修正を実行し、それらを保存しようとしています。名前空間の命名法。例:

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

コードスニペットは以下のとおりです。

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;

register_namespaceを使用しようとしましたが、肯定的な結果は得られませんでした。このバージョンのElementTree 1.3に特定の変更はありますか?

40
ilya1725

ns0プレフィックスを回避するには、デフォルトのネームスペースを設定する必要がありますbefore XMLデータの読み取り。

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

すべての名前空間を登録する必要があります。

例:このような入力xmlがある場合

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

次に、すべての名前空間、つまり次のようにxmlnsで存在する属性を登録する必要があります。

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

この回答は、ns0の問題を回避するのに非常に役立ちました。 GPXをGPaws(動作する場合)からKML(Googleマップ用)に変換していますが、このようなデフォルトの名前空間を設定するまでコードは機能しませんでしたET.register_namespace("","http://www.opengis.net/kml/2.2")

1
user3604332

名前空間を宣言する必要があるようです。つまり、xmlの最初の行を次のように変更する必要があります。

<ns0:trk>

次のようなものに:

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

一度やると、もうParseError: for unbound prefix: ...、および:

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

名前空間を削除します。

0
Rik Poggi