Невозможно разобрать xml в python [duplicate]

Это было в моем .htaccess

DirectoryIndex index.html index.htm

index.html, содержащем PHP-код. По умолчанию PHP не будет обрабатывать файлы с такими расширениями, как htm *, как PHP-код.

Вы можете переопределить это, добавив следующее в .htaccess:

<FilesMatch ".+\.html$">
    SetHandler application/x-httpd-php
</FilesMatch>
119
задан DavidRR 13 January 2015 в 15:59
поделиться

6 ответов

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

167
ответ дан Martijn Pieters 19 August 2018 в 05:48
поделиться
  • 1
    Спасибо. Любая идея, как я могу получить пространство имен непосредственно из XML, без жесткого кодирования? Или как я могу игнорировать его? Я пробовал findall ('{*} Class'), но он не будет работать в моем случае. – Kostanos 27 November 2013 в 03:26
  • 2
    Вам придется сканировать дерево для атрибутов xmlns самостоятельно; как указано в ответе, lxml делает это для вас, модуль xml.etree.ElementTree не делает этого. Но если вы пытаетесь сопоставить определенный (уже жестко закодированный) элемент, то вы также пытаетесь сопоставить определенный элемент в определенном пространстве имен. Это пространство имен не будет меняться между документами больше, чем имя элемента. Вы можете также указать жесткий код с именем элемента. – Martijn Pieters♦ 28 November 2013 в 17:12
  • 3
    Почему register_namespace не работает? – Jon 20 August 2014 в 08:06
  • 4
    @Jon: register_namespace влияет только на сериализацию, а не на поиск. – Martijn Pieters♦ 20 August 2014 в 08:10
  • 5
    Небольшое дополнение, которое может быть полезно: при использовании cElementTree вместо ElementTree, findall не будет принимать пространства имен в качестве аргумента ключевого слова, а скорее просто как обычный аргумент, т. Е. Использовать ctree.findall('owl:Class', namespaces). – egpbos 30 September 2014 в 16:18

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

from lxml import etree
tree = etree.parse("filename")
root = tree.getroot()
root.findall('owl:Class', root.nsmap)
42
ответ дан Brad Dre 19 August 2018 в 05:48
поделиться
  • 1
    это работает отлично. – Brandon Kuczenski 16 August 2015 в 00:05
  • 2
    Полный URL-адрес пространства имен - это идентификатор пространства имен, который вы должны жестко кодировать. Локальный префикс (owl) может меняться от файла к файлу. Поэтому делать то, что предлагает этот ответ, - очень плохая идея. – Matti Virkkunen 18 March 2016 в 22:53
  • 3
    @MattiVirkkunen точно, если определение совы может измениться из файла в файл, разве мы не должны использовать определение, определенное в каждом файле, а не hardcoding? – Loïc Faure-Lacroix 1 August 2016 в 03:26
  • 4
    @ LoïcFaure-Lacroix: Обычно библиотеки XML позволят вам абстрагировать эту часть. Вам не нужно даже знать или заботиться о префиксе, который используется в самом файле, вы просто определяете свой собственный префикс для разбора или просто используете полное имя пространства имен. – Matti Virkkunen 5 August 2016 в 01: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 19 August 2018 в 05:48
поделиться
  • 1
    Это полезно для тех из нас, кто не имеет доступа к lxml и не хочет использовать пространство имен hardcode. – delrocco 6 June 2016 в 02:41
  • 2
    Я получил ошибку: ValueError: write to closed для этой строки filemy_namespaces = dict([node for _, node in ET.iterparse(StringIO(my_schema), events=['start-ns'])]). Любая идея хочет не так? – Yuli 20 February 2017 в 13:03
  • 3
    Вероятно, ошибка связана с классом io.StringIO, который отказывается от строк ASCII. Я тестировал свой рецепт с Python3. Добавляем строковый префикс unicode 'u' к строке образца, который он также работает с Python 2 (2.7). – Davide Brunato 21 February 2017 в 09:23
  • 4
    Вместо dict([...]) вы также можете использовать понимание dict. – Arminius 1 November 2017 в 22:07
  • 5
    Вместо StringIO(my_schema) вы также можете поместить имя файла XML. – JustAC0der 29 June 2018 в 18:57

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

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 19 August 2018 в 05:48
поделиться

Я знаю, что я опаздываю на несколько лет, но я только что создал пакет, который будет обрабатывать преобразование словаря в действительный 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 19 August 2018 в 05:48
поделиться
0
ответ дан Bram Vanroy 30 October 2018 в 17:55
поделиться
Другие вопросы по тегам:

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