Frage

Wie kann man auf NS -Attribute zugreifen, indem man ElementTree verwendet?

Mit den folgenden:

<data xmlns="http://www.foo.net/a" xmlns:a="http://www.foo.net/a" book="1" category="ABS" date="2009-12-22">

Wenn ich versuche, zu root.get ('xmlns'), bekomme ich keine zurück, Kategorie und Datum sind in Ordnung, jede Hilfe geschätzt.

Keine korrekte Lösung

Andere Tipps

Ich finde element.tag ist was Sie suchen. Beachten Sie, dass Ihrem Beispiel einen nachverfolgenden Schrägstrich fehlt, es ist also unausgeglichen und nicht analysiert. Ich habe in meinem Beispiel einen hinzugefügt.

>>> from xml.etree import ElementTree as ET
>>> data = '''<data xmlns="http://www.foo.net/a"
...                 xmlns:a="http://www.foo.net/a"
...                 book="1" category="ABS" date="2009-12-22"/>'''
>>> element = ET.fromstring(data)
>>> element
<Element {http://www.foo.net/a}data at 1013b74d0>
>>> element.tag
'{http://www.foo.net/a}data'
>>> element.attrib
{'category': 'ABS', 'date': '2009-12-22', 'book': '1'}

Wenn Sie nur den XMLNS -URI kennen möchten, können Sie ihn mit einer Funktion wie:

def tag_uri_and_name(elem):
    if elem.tag[0] == "{":
        uri, ignore, tag = elem.tag[1:].partition("}")
    else:
        uri = None
        tag = elem.tag
    return uri, tag

Für viel mehr in Namespaces und qualifizierten Namen in ElementTree siehe Beispiele von Effbot.

Schauen Sie sich die Dokumentation/Beispiele für Effbot -Namespaces an. speziell die Parse_map Funktion. Es wird angezeigt, wie Sie jedem Element ein * ns_map * -Merkmal hinzufügen, das das Präfix/URI -Zuordnung enthält, das für dieses spezifische Element gilt.

Dies fügt jedoch das NS_MAP -Attribut zu allen Elementen hinzu. Für meine Bedürfnisse wollte ich eine globale Karte aller Namespaces, mit denen das Element einfacher und nicht festcodiert wird.

Folgendes habe ich mir ausgedacht:

import elementtree.ElementTree as ET

def parse_and_get_ns(file):
    events = "start", "start-ns"
    root = None
    ns = {}
    for event, elem in ET.iterparse(file, events):
        if event == "start-ns":
            if elem[0] in ns and ns[elem[0]] != elem[1]:
                # NOTE: It is perfectly valid to have the same prefix refer
                #     to different URI namespaces in different parts of the
                #     document. This exception serves as a reminder that this
                #     solution is not robust.    Use at your own peril.
                raise KeyError("Duplicate prefix with different URI found.")
            ns[elem[0]] = "{%s}" % elem[1]
        elif event == "start":
            if root is None:
                root = elem
    return ET.ElementTree(root), ns

Damit können Sie eine XML -Datei analysieren und mit den Namespace -Zuordnungen ein Diktat erhalten. Also, wenn Sie eine XML -Datei wie folgt haben ("my.xml"):

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"\
>
<feed>
  <item>
    <title>Foo</title>
    <dc:creator>Joe McGroin</dc:creator>
    <description>etc...</description>
  </item>
</feed>
</rss>

Sie können die XML -Neamepaces verwenden und Informationen für Elemente wie erhalten DC: Schöpfer:

>>> tree, ns = parse_and_get_ns("my.xml")
>>> ns
{u'content': '{http://purl.org/rss/1.0/modules/content/}',
u'dc': '{http://purl.org/dc/elements/1.1/}'}
>>> item = tree.find("/feed/item")
>>> item.findtext(ns['dc']+"creator")
'Joe McGroin'

Versuche dies:

import xml.etree.ElementTree as ET
import re
import sys

with open(sys.argv[1]) as f:
    root = ET.fromstring(f.read())
    xmlns = ''
    m = re.search('{.*}', root.tag)
    if m:
        xmlns = m.group(0)
    print(root.find(xmlns + 'the_tag_you_want').text)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top