Извлечь список элементов из XML в python - PullRequest
1 голос
/ 11 мая 2011

В Python, каков наилучший способ извлечь список элементов из следующего XML?

<iq xmlns="jabber:client" to="__anonymous__admin@localhost/8978528613056092673206" 
 from="conference.localhost" id="disco" type="result">
    <query xmlns="http://jabber.org/protocol/disco#items">
        <item jid="pgatt@conference.localhost" name="pgatt (1)"/>
        <item jid="pgatt@conference.localhost" name="pgatt (1)"/>
    </query>
</iq>

Я обычно использую lxml с xpath, но в этом случае он не работает.Я думаю, что мои проблемы связаны с пространством имен.Я не настроен на lxml и могу использовать любую библиотеку.

Я хотел бы получить достаточно надежное решение, чтобы оно не работало, если общая структура xml меняется.

Ответы [ 3 ]

1 голос
/ 11 мая 2011

Ранее я ответил на аналогичный вопрос о том, как анализировать и выполнять поиск в данных XML.

Полнотекстовый поиск данных XML с помощью Python: лучшие практики, плюсы и минусы

Вы захотите взглянуть на функцию xml2json. Функция ожидает объект минидома. Вот как я получил свой XML, не уверен, как вы это делаете.

from xml.dom import minidom
x = minidom.parse(urllib.urlopen(url))
json = xml2json(x)

Или, если вы используете строку, а не URL:

x = minidom.parseString(xml_string)
json = xml2json(x)

Функция xml2json вернет словарь со всеми значениями, найденными в xml. Возможно, вам придется попробовать и распечатать вывод, чтобы увидеть, как выглядит макет.

1 голос
/ 11 мая 2011

Я не уверен насчет lxml, но вы можете использовать выражение типа //*[local-name()="item"] для извлечения элементов item независимо от их пространства имен.

Возможно, вы захотите взглянуть на Amara для обработки XML.

>>> import amara.bindery
>>> doc = amara.bindery.parse(
...     '''<iq xmlns="jabber:client" 
...          to="__anonymous__admin@localhost/8978528613056092673206"
...          from="conference.localhost" id="disco" type="result">
...          <query xmlns="http://jabber.org/protocol/disco#items">
...            <item jid="pgatt@conference.localhost" name="pgatt (1)"/>
...            <item jid="pgatt@conference.localhost" name="pgatt (1)"/>
...          </query>
...        </iq>''')
>>> for item in doc.iq.query.item:
...   print item.jid, item.name
...
pgatt@conference.localhost pgatt (1)
pgatt@conference.localhost pgatt (1)
>>>

Как только я обнаружил Амару, я бы никогда не подумал об обработке XML каким-либо другим способом.

0 голосов
/ 11 мая 2011

Я пропустил лодку, но вот как вы это делаете, заботясь о пространствах имен.

Вы можете либо записать их все в запросе, либо создать карту пространства имен, которую вы передадите в запрос xpath.

from lxml import etree

data = """<iq xmlns="jabber:client" to="__anonymous__admin@localhost/8978528613056092673206"
 from="conference.localhost" id="disco" type="result">
    <query xmlns="http://jabber.org/protocol/disco#items">
        <item jid="pgatt@conference.localhost" name="pgatt (1)"/>
        <item jid="pgatt@conference.localhost" name="pgatt (1)"/>
    </query>
</iq>"""

nsmap = {
  'jc': "jabber:client",
  'di':"http://jabber.org/protocol/disco#items"
}

doc = etree.XML(data)

for item in doc.xpath('//jc:iq/di:query/di:item',namespaces=nsmap):
  print etree.tostring(item).strip()
  print "Name: %s\nJabberID: %s\n" % (item.attrib.get('name'),item.attrib.get('jid'))

Производит:

<item xmlns="http://jabber.org/protocol/disco#items" jid="pgatt@conference.localhost" name="pgatt (1)"/>
Name: pgatt (1)
JabberID: pgatt@conference.localhost

<item xmlns="http://jabber.org/protocol/disco#items" jid="pgatt@conference.localhost" name="pgatt (1)"/>
Name: pgatt (1)
JabberID: pgatt@conference.localhost
...