Ich habe das folgende XML, das ich mit Pythons analysieren möchte ElementTree
:
<rdf:RDF xml:base="http://dbpedia.org/ontology/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns="http://dbpedia.org/ontology/">
<owl:Class rdf:about="http://dbpedia.org/ontology/BasketballLeague">
<rdfs:label xml:lang="en">basketball league</rdfs:label>
<rdfs:comment xml:lang="en">
a group of sports teams that compete against each other
in Basketball
</rdfs:comment>
</owl:Class>
</rdf:RDF>
Ich möchte alle owl:Class
Tags finden und dann den Wert aller darin enthaltenen rdfs:label
Instanzen extrahieren . Ich verwende den folgenden Code:
tree = ET.parse("filename")
root = tree.getroot()
root.findall('owl:Class')
Aufgrund des Namespace wird der folgende Fehler angezeigt.
SyntaxError: prefix 'owl' not found in prefix map
Ich habe versucht, das Dokument unter http://effbot.org/zone/element-namespaces.htm zu lesen, aber ich kann dies immer noch nicht zum Laufen bringen, da das obige XML mehrere verschachtelte Namespaces hat.
Bitte lassen Sie mich wissen, wie Sie den Code ändern können, um alle owl:Class
Tags zu finden .
xmlns
Attributen durchsuchen. Wie in der Antwort angegeben,lxml
erledigt dies für Sie, dasxml.etree.ElementTree
Modul nicht. Wenn Sie jedoch versuchen, ein bestimmtes (bereits fest codiertes) Element abzugleichen, versuchen Sie auch, ein bestimmtes Element in einem bestimmten Namespace abzugleichen. Dieser Namespace ändert sich zwischen Dokumenten nicht mehr als der Elementname. Sie können dies auch mit dem Elementnamen fest codieren.register_namespace
Beeinflusst nur die Serialisierung, nicht die Suche.cElementTree
anstelle von verwendenElementTree
,findall
werden Namespaces nicht als Schlüsselwortargument verwendet, sondern einfach als normales Argument, dh als Verwendungctree.findall('owl:Class', namespaces)
.findall
without und dann mit demnamespace
Argument kontrastiert. Das Argument wird jedoch nicht als eines der Argumente für die Methodenmethode im Abschnitt Element object erwähnt .So geht's mit lxml, ohne die Namespaces fest codieren oder den Text nach ihnen durchsuchen zu müssen (wie Martijn Pieters erwähnt):
UPDATE :
5 Jahre später stoße ich immer noch auf Variationen dieses Problems. lxml hilft wie oben gezeigt, aber nicht in jedem Fall. Die Kommentatoren mögen einen gültigen Punkt in Bezug auf diese Technik haben, wenn es darum geht, Dokumente zusammenzuführen, aber ich denke, die meisten Leute haben Schwierigkeiten, einfach Dokumente zu suchen.
Hier ist ein weiterer Fall und wie ich damit umgegangen bin:
xmlns ohne Präfix bedeutet, dass nicht vorfixierte Tags diesen Standard-Namespace erhalten. Dies bedeutet, dass Sie bei der Suche nach Tag2 den Namespace angeben müssen, um ihn zu finden. Lxml erstellt jedoch einen nsmap-Eintrag mit None als Schlüssel, und ich konnte keine Möglichkeit finden, danach zu suchen. Also habe ich ein neues Namespace-Wörterbuch wie dieses erstellt
quelle
owl
) kann sich von Datei zu Datei ändern. Daher ist es eine wirklich schlechte Idee, das zu tun, was diese Antwort nahelegt.Hinweis : Dies ist eine nützliche Antwort für die ElementTree-Standardbibliothek von Python, ohne fest codierte Namespaces zu verwenden.
Um die Präfixe und URI des Namespace aus XML-Daten zu extrahieren, können Sie die
ElementTree.iterparse
Funktion verwenden und nur Namespace -Startereignisse ( Start-ns ) analysieren :Dann kann das Wörterbuch als Argument an die Suchfunktionen übergeben werden:
quelle
ValueError: write to closed
für diese Zeilefilemy_namespaces = dict([node for _, node in ET.iterparse(StringIO(my_schema), events=['start-ns'])])
. Irgendeine Idee will falsch?dict([...])
können Sie auch das Diktatverständnis verwenden.StringIO(my_schema)
können Sie auch den Dateinamen der XML-Datei eingeben.Ich habe einen ähnlichen Code verwendet und festgestellt, dass es sich immer lohnt, die Dokumentation zu lesen ... wie immer!
findall () findet nur Elemente, die direkte untergeordnete Elemente des aktuellen Tags sind . Also nicht wirklich ALLE.
Es kann sich lohnen, zu versuchen, Ihren Code mit den folgenden Funktionen zum Laufen zu bringen, insbesondere wenn Sie mit großen und komplexen XML-Dateien arbeiten, sodass auch Unter-Unterelemente (usw.) enthalten sind. Wenn Sie selbst wissen, wo sich Elemente in Ihrer XML befinden, ist das wahrscheinlich in Ordnung! Ich dachte nur, das wäre es wert, in Erinnerung zu bleiben.
ref: https://docs.python.org/3/library/xml.etree.elementtree.html#finding-interesting-elements "Element.findall () findet nur Elemente mit einem Tag, die direkte untergeordnete Elemente des aktuellen Elements sind. Element.find () findet das erste untergeordnete Element mit einem bestimmten Tag und Element.text greift auf den Textinhalt des Elements zu. Element.get () greift auf die Attribute des Elements zu: "
quelle
Um den Namespace in seinem Namespace-Format zu erhalten,
{myNameSpace}
können Sie beispielsweise Folgendes tun:Auf diese Weise können Sie es später in Ihrem Code verwenden, um Knoten zu finden, z. B. mithilfe der Zeichenfolgeninterpolation (Python 3).
quelle
Meine Lösung basiert auf dem Kommentar von @Martijn Pieters:
Der Trick hier besteht also darin, verschiedene Wörterbücher für die Serialisierung und für die Suche zu verwenden.
Registrieren Sie jetzt alle Namespaces zum Parsen und Schreiben:
Für die Suche (
find()
,findall()
,iterfind()
) brauchen wir einen nicht leeren Präfix. Übergeben Sie diesen Funktionen ein geändertes Wörterbuch (hier ändere ich das ursprüngliche Wörterbuch, dies muss jedoch erst erfolgen, nachdem die Namespaces registriert wurden).Jetzt können die Funktionen aus der
find()
Familie mit demdefault
Präfix verwendet werden:aber
verwendet keine Präfixe für Elemente im Standard-Namespace.
quelle