python xml iter с неработающим тегом [duplicate]

115
задан DavidRR 13 January 2015 в 15:59
поделиться

5 ответов

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 для элементов.

169
ответ дан Martijn Pieters 5 September 2018 в 10:40
поделиться

Вот как это сделать с помощью lxml без необходимости жесткого кодирования пространств имен или сканирования текста для них (как упоминает Martijn Pieters):

from lxml import etree
tree = etree.parse("filename")
root = tree.getroot()
root.findall('owl:Class', root.nsmap)
42
ответ дан Brad Dre 5 September 2018 в 10:40
поделиться

Примечание : Это ответ полезен для стандартной библиотеки 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)
13
ответ дан Davide Brunato 5 September 2018 в 10:40
поделиться

Я использовал аналогичный код для этого и нашел, что всегда стоит читать документацию ... как обычно!

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 () обращается к атрибутам элемента: "

3
ответ дан MJM 5 September 2018 в 10:40
поделиться

Я знаю, что я опаздываю на несколько лет, но я только что создал пакет, который будет обрабатывать преобразование словаря в действительный 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>

Надеюсь, это полезно для людей в будущем

1
ответ дан watzon 5 September 2018 в 10:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: