получение определенных атрибутов узлов XML - PullRequest
1 голос
/ 11 февраля 2010

Это может быть вопрос новичка :), но меня это раздражает, так как я новичок в XML. У меня есть следующий XML-файл:

<assetsMain>
  <assetParent type='character' shortName='char'>
    <asset>
      pub
    </asset>
    <asset>
      car
    </asset>
  </assetParent>
  <assetParent type='par' shortName='pr'>
    <asset>
      camera
    </asset>
    <asset>
      rig
    </asset>
  </assetParent>
</assetsMain>

Можно ли извлечь все <assetParent> узлы и все их атрибуты и дочерние тексты? Например, чтобы получить следующий результат:

[ [['character','char'],['pub','car']]
  [['par','pr'],['camera','rig']]
]

Кстати, я использую DOM и Python 2.6

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 11 февраля 2010

Ответ с использованием lxml.etree. Вероятно, Xpath можно будет использовать в другой работающей библиотеке:

>>> from lxml import etree
>>> data = """<assetsMain>
... <assetParent type='character' shortName='char'>
... <asset>pub</asset>
... <asset>car</asset>
... </assetParent>
... <assetParent type='par' shortName='pr'>
... <asset>camera</asset>
... <asset>rig</asset>
... </assetParent>
... </assetsMain>
... """
>>> doc = etree.XML(data)
>>> for aP in doc.xpath('//assetParent'):
...   parent = aP.attrib['type']
...   for a in aP.xpath('./asset/text()'):
...     print parent, a.strip()
...
character pub
character car
par camera
par rig
0 голосов
/ 11 февраля 2010

Этот код дает желаемый результат:

from xml.dom.minidom import parseString

document = """\
<assetsMain>
  <assetParent type='character' shortName='char'>
    <asset>
      pub
    </asset>
    <asset>
      car
    </asset>
  </assetParent>
  <assetParent type='par' shortName='pr'>
    <asset>
      camera
    </asset>
    <asset>
      rig
    </asset>
  </assetParent>
</assetsMain>
"""

def getNestedList():
    dom = parseString(document)
    li = []
    for assetParent in dom.childNodes[0].getElementsByTagName("assetParent"):
        # read type and shortName
        a = [assetParent.getAttribute("type"), assetParent.getAttribute("shortName")]
        # read content of asset nodes
        b = [asset.childNodes[0].data.strip() for asset in assetParent.getElementsByTagName("asset")]
        # put the lists together in a list and add them to the list (!)
        li.append([a,b])
    return li

if __name__=="__main__":
    print getNestedList()

Обратите внимание, что мы можем выбрать, какие дочерние узлы мы хотим прочитать с помощью getElementsByTagName. Атрибуты читаются с getAttribute на узле. Текстовое содержимое внутри узла читается через свойство data (сам текст также является дочерним узлом). Если вы читаете текст внутри узла, вы можете проверить, что это действительно текст:

if node.nodeType == node.TEXT_NODE:

Также обратите внимание, что здесь нет проверки или обработки ошибок. Узлы, не имеющие дочерних узлов, вызовут IndexError.

Хотя из-за вложенного списка из трех уровней я хочу предложить вам использовать словари.

Выход:

[[[u'character', u'char'], [u'pub', u'car']], [[u'par', u'pr'], [u'camera', u'rig']]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...