获取特定XML节点属性

1 投票
2 回答
807 浏览
提问于 2025-04-15 19:09

这可能是个新手问题 :) 但我因为刚接触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 个回答

0

这段代码会输出你想要的结果:

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']]]
3

这是一个使用 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

撰写回答