在Python中从XML子树中获取唯一标签值

2 投票
2 回答
966 浏览
提问于 2025-04-16 05:46

我有一个叫 getElementText 的函数,它在处理我正在使用的 XML 时效果很好,因为这个 XML 里没有重复的标签。

from xml.dom import minidom

def getElementText(element, tagName):
    return str(element.getElementsByTagName(tagName)[0].firstChild.data)

doc = minidom.parse("/Users/smcho/Desktop/hello.xml")
outputTree = doc.getElementsByTagName("Output")[0]

print getElementText(outputTree, "Number") 

但是,当我解析下面这个 XML 时,我无法获取到值 <Number>0</Number>,而是得到了 <ConnectedTerminal><Number>1</Number></ConnectedTerminal>,这是因为 getElementText 函数只返回第一个标签为 "Number" 的元素。

<Output>
  <ConnectedTerminal>
    <Node>5</Node>
    <Number>1</Number>
  </ConnectedTerminal>
  <Type>int8</Type>
  <Number>0</Number>
</Output>

有没有什么解决办法?有没有办法只获取到 <Number>0</Number> 或者 <ConnectedTerminal><Number>1</Number></ConnectedTerminal> 呢?

2 个回答

0

没有直接的方法可以做到这一点。不过,写一个这样的功能其实很简单:

def getChildElementsByTagName(element, tag):
    children= []
    for child in element.childNodes:
        if child.nodeType==child.ELEMENT_NODE and tag in (child.tagName, '*'):
            children.push(child)
    return children

另外,这里有一个更安全的获取文本的函数,这样你就不用担心多个节点、因为空字符串而缺失的节点,或者CDATA部分的问题了。

def getTextContent(element):
    texts= []
    for child in element.childNodes:
        if child.nodeType==child.ELEMENT_NODE:
            texts.append(getTextContent(child))
        elif child.nodeType==child.TEXT_NODE:
            texts.append(child.data)
    return u''.join(texts)

然后只需要:

>>> getTextContent(getChildElementsByTagName(doc, u'Number')[0])
u'0'
>>> getTextContent(getChildElementsByTagName(doc, u'Output')[0].getElementsByTagName(u'Number')[0])
u'1'
3

如果你可以使用 lxml 这个库(它比 minidom 要好用得多),你可以这样做:

from lxml import etree

doc = etree.fromstring(xml)

node = doc.find('Number')
print node.text # 0

node = doc.xpath('//ConnectedTerminal/Number')[0]
print node.text # 1

另外,你还可以查看这个 xpath 的教程。

撰写回答