ElementTree не слишком разбирается в пространствах имен. Вы должны дать методам .find()
, findall()
и iterfind()
явный словарь пространств имен. Это не очень хорошо документировано:
namespaces = {'owl': 'http://www.w3.org/2002/07/owl#'} # add more as needed
root.findall('owl:Class', namespaces)
Префиксы только просмотрены в параметре namespaces
, который вы проходите. Это означает, что вы можете использовать любой префикс пространства имен, который вам нравится; API отделяет часть owl:
, просматривает соответствующий URL-адрес пространства имен в словаре namespaces
, а затем изменяет поиск, чтобы искать выражение XPath {http://www.w3.org/2002/07/owl}Class
. Вы тоже можете использовать тот же синтаксис:
root.findall('{http://www.w3.org/2002/07/owl#}Class')
Если вы можете переключиться на библиотеку lxml
, все будет лучше; эта библиотека поддерживает один и тот же API ElementTree, но собирает пространства имен для вас в атрибуте .nsmap
для элементов.
Вот как это сделать с помощью lxml без необходимости жесткого кодирования пространств имен или сканирования текста для них (как упоминает Martijn Pieters):
from lxml import etree
tree = etree.parse("filename")
root = tree.getroot()
root.findall('owl:Class', root.nsmap)
Примечание : Это ответ полезен для стандартной библиотеки Python ElementTree без использования жестко заданных пространств имен.
Чтобы извлечь префиксы и URI из пространства имен из данных XML, вы можете использовать функцию ElementTree.iterparse
, разбор только событий начала пространства имен ( start-ns ):
>>> from io import StringIO
>>> from xml.etree import ElementTree
>>> my_schema = u'''<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>'''
>>> my_namespaces = dict([
... node for _, node in ElementTree.iterparse(
... StringIO(my_schema), events=['start-ns']
... )
... ])
>>> from pprint import pprint
>>> pprint(my_namespaces)
{'': 'http://dbpedia.org/ontology/',
'owl': 'http://www.w3.org/2002/07/owl#',
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
'xsd': 'http://www.w3.org/2001/XMLSchema#'}
Затем словарь может быть передан как аргумент в функции поиска:
root.findall('owl:Class', my_namespaces)
Я использовал аналогичный код для этого и нашел, что всегда стоит читать документацию ... как обычно!
findall () будет находить только элементы, которые являются прямыми дочерними элементами текущий тег . Итак, не совсем ВСЕ.
Возможно, вам стоит попробовать, чтобы ваш код работал со следующим, особенно если вы имеете дело с большими и сложными файлами xml, чтобы эти под-элементы ( и т. д.). Если вы знаете, где находятся элементы в вашем xml, я полагаю, все будет хорошо! Просто подумал, что это стоит вспомнить.
root.iter()
ref: https://docs.python.org/3/library/xml.etree.elementtree.html#finding-interesting-elements «Element.findall () находит только элементы с тегом, которые являются прямыми дочерними элементами текущего элемента. Element.find () находит первого дочернего элемента с определенным тегом, а Element.text обращается к текстовому содержимому элемента. Элемент. get () обращается к атрибутам элемента: "
Я знаю, что я опаздываю на несколько лет, но я только что создал пакет, который будет обрабатывать преобразование словаря в действительный XML с пространствами имен. Пакет размещен на PyPi @ https://pypi.python.org/pypi/xmler .
Используя этот пакет, вы можете взять словарь, который выглядит так:
myDict = {
"RootTag": { # The root tag. Will not necessarily be root. (see #customRoot)
"@ns": "soapenv", # The namespace for the RootTag. The RootTag will appear as <soapenv:RootTag ...>
"@attrs": { # @attrs takes a dictionary. each key-value pair will become an attribute
{ "xmlns:soapenv": "http://schemas.xmlsoap.org/soap/envelope/" }
},
"childTag": {
"@attrs": {
"someAttribute": "colors are nice"
},
"grandchild": "This is a text tag"
}
}
}
и получить XML-вывод, который выглядит следующим образом:
<soapenv:RootTag xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<childTag someAttribute="colors are nice">
<grandchild>This is a text tag</grandchild>
</childTag>
</soapenv:RootTag>
Надеюсь, это полезно для людей в будущем