Saya memiliki XML berikut yang ingin saya parsing menggunakan Python 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>
Saya ingin menemukan semua owl:Class
tag lalu mengekstraksi nilai semua rdfs:label
instance di dalamnya. Saya menggunakan kode berikut:
tree = ET.parse("filename")
root = tree.getroot()
root.findall('owl:Class')
Karena namespace, saya mendapatkan kesalahan berikut.
SyntaxError: prefix 'owl' not found in prefix map
Saya mencoba membaca dokumen di http://effbot.org/zone/element-namespaces.htm tapi saya masih tidak bisa membuatnya berfungsi karena XML di atas memiliki beberapa ruang nama bersarang.
Mohon beri tahu saya cara mengubah kode untuk menemukan semua owl:Class
tag.
xmlns
atribut sendiri; seperti yang dinyatakan dalam jawaban,lxml
apakah ini untuk Anda,xml.etree.ElementTree
modul tidak. Tetapi jika Anda mencoba untuk mencocokkan elemen tertentu (sudah hardcod), maka Anda juga mencoba untuk mencocokkan elemen tertentu dalam namespace tertentu. Namespace itu tidak akan berubah di antara dokumen seperti halnya nama elemen. Anda juga dapat melakukan hardcode dengan nama elemen.register_namespace
hanya memengaruhi serialisasi, bukan pencarian.cElementTree
alih-alihElementTree
,findall
tidak akan menggunakan spasi nama sebagai argumen kata kunci, melainkan sebagai argumen normal, yaitu penggunaanctree.findall('owl:Class', namespaces)
.findall
tanpa dan kemudian dengannamespace
argumen, tetapi argumen tidak disebutkan sebagai salah satu argumen untuk metode metode di bagian objek Elemen .Berikut ini cara melakukannya dengan lxml tanpa harus membuat hard-namespaces atau memindai teks untuknya (seperti yang disebutkan Martijn Pieters):
PEMBARUAN :
5 tahun kemudian saya masih mengalami variasi masalah ini. lxml membantu seperti yang saya tunjukkan di atas, tetapi tidak dalam setiap kasus. Para komentator mungkin memiliki poin yang valid mengenai teknik ini ketika menggabungkan dokumen, tetapi saya pikir kebanyakan orang mengalami kesulitan hanya dengan mencari dokumen.
Ini kasus lain dan bagaimana saya menanganinya:
xmlns tanpa awalan berarti bahwa tag yang tidak diperbaiki mendapatkan namespace default ini. Ini berarti ketika Anda mencari Tag2, Anda harus memasukkan namespace untuk menemukannya. Namun, lxml membuat entri nsmap dengan None sebagai kuncinya, dan saya tidak dapat menemukan cara untuk mencarinya. Jadi, saya membuat kamus namespace baru seperti ini
sumber
owl
) dapat berubah dari file ke file. Oleh karena itu melakukan apa yang disarankan jawaban ini adalah ide yang sangat buruk.Catatan : Ini adalah jawaban yang berguna untuk perpustakaan standar ElementTree Python tanpa menggunakan ruang nama yang di-hardcode.
Untuk mengekstrak awalan namespace dan URI dari data XML Anda dapat menggunakan
ElementTree.iterparse
fungsi, hanya mem-parsing peristiwa mulai namespace ( start-ns ):Kemudian kamus dapat diteruskan sebagai argumen ke fungsi pencarian:
sumber
ValueError: write to closed
untuk baris inifilemy_namespaces = dict([node for _, node in ET.iterparse(StringIO(my_schema), events=['start-ns'])])
. Ada ide yang salah?dict([...])
Anda juga dapat menggunakan pemahaman dict.StringIO(my_schema)
Anda juga bisa meletakkan nama file file XML.Saya telah menggunakan kode yang mirip dengan ini dan telah menemukan selalu layak membaca dokumentasi ... seperti biasa!
findall () hanya akan menemukan elemen yang merupakan anak-anak langsung dari tag saat ini . Jadi, tidak benar-benar SEMUA.
Mungkin bernilai saat Anda mencoba agar kode Anda berfungsi dengan yang berikut, terutama jika Anda berurusan dengan file xml yang besar dan kompleks sehingga sub-elemen (dll) juga disertakan. Jika Anda tahu sendiri di mana elemen berada di xml Anda, maka saya kira itu akan baik-baik saja! Hanya berpikir ini layak diingat.
ref: https://docs.python.org/3/library/xml.etree.elementtree.html#finding-interesting-elements "Element.findall () menemukan hanya elemen dengan tag yang merupakan anak-anak langsung dari elemen saat ini. Element.find () menemukan anak pertama dengan tag tertentu, dan Element.text mengakses konten teks elemen. Element.get () mengakses atribut elemen: "
sumber
Untuk mendapatkan namespace dalam format namespace, misalnya
{myNameSpace}
, Anda dapat melakukan hal berikut:Dengan cara ini, Anda dapat menggunakannya nanti dalam kode Anda untuk menemukan node, misalnya menggunakan interpolasi string (Python 3).
sumber
Solusi saya didasarkan pada komentar @Martijn Pieters ':
Jadi triknya di sini adalah menggunakan kamus yang berbeda untuk serialisasi dan untuk pencarian.
Sekarang, daftarkan semua ruang nama untuk parsing dan menulis:
Untuk mencari (
find()
,findall()
,iterfind()
) kita perlu awalan non-kosong. Lulus fungsi-fungsi ini kamus yang dimodifikasi (di sini saya memodifikasi kamus asli, tetapi ini harus dibuat hanya setelah ruang nama terdaftar).Sekarang, fungsi-fungsi dari
find()
keluarga dapat digunakan dengandefault
awalan:tapi
tidak menggunakan awalan untuk elemen di namespace default.
sumber