Python 如何找到没有属性的xml节点

Python 如何找到没有属性的xml节点,python,xml-parsing,Python,Xml Parsing,我正在使用Python2.7并尝试解析下面的XML—我正在尝试创建一个包含所有类型的python数组,其中包含一个带有语言属性的数组和一个没有语言属性的数组 我正在使用python模块import xml.etree.cElementTree作为ET 我知道我可以通过语法找到XML部分,其中language属性是“fr”语言: tree=ET.ElementTree(file='popups.xml') root = tree.getroot() for x in root.findall('a

我正在使用Python2.7并尝试解析下面的XML—我正在尝试创建一个包含所有类型的python数组,其中包含一个带有语言属性的数组和一个没有语言属性的数组

我正在使用python模块
import xml.etree.cElementTree作为ET

我知道我可以通过语法找到XML部分,其中language属性是“fr”语言:

tree=ET.ElementTree(file='popups.xml') root = tree.getroot() for x in root.findall('alt[@{http://www.w3.org/XML/1998/namespace}lang="fr"]/alt'): print x.text 我真的不明白为什么不能使用xml:lang而不是{http://www.w3.org/XML/1998/namespace}lang,但上面的内容似乎在Ubuntu 12.04上可以使用

使用
xpath
方法(在
cElementTree
中不可用)可以更轻松地完成您要做的事情,该方法将从文档的根元素读取名称空间标签,因此您可以问:

import lxml.etree as et

root = et.parse(open('mydoc.xml')).getroot()

for x in root.xpath('alt[not(@xml:lang)]/alt'):
    print x.text

not(@attr)
语法我以前不熟悉,但是在谷歌搜索“xpath查找不带属性的元素”非常有用。

您需要在xpath中使用完整的QName,因为stdlib ElementTree没有注册前缀的方法。我通常使用助手函数来创建QName:

def qname(prefix, element, map={'xml':'http://www.w3.org/XML/1998/namespace'}):
    return "{{{}}}{}".format(map[prefix], element)
标准库中的
ElementTree
实现不支持足够的XPath,无法轻松完成所需的操作。但是,指定此属性的值由包含它的所有内容继承,有点像
xml:base
xmlns
命名空间声明。因此,作为替代方案,我们可以在所有元素上明确语言设置:

xml_lang = qname('xml', 'lang')

def set_xml_lang(root, defaultlang=''):
    xml_lang = qname('xml', 'lang')
    for item in root:
        try:
            lang = item.attrib[xml_lang]
        except KeyError, err:
            item.set(xml_lang, defaultlang)
            lang = defaultlang
        set_xml_lang(item, lang)

set_xml_lang(root)

namespaces = {'xml':'http://www.w3.org/XML/1998/namespace'}
# Every element in root now has an xml:lang attribute
# so XPath is easy now:
alts_with_no_lang = root.findall('alt[@{{{xml}}}lang=""]'.format(**namespaces))
如果您愿意使用,则“lang”的使用会更加健壮,因为它遵循完整的XPath 1.0规范。特别是,您可以使用
lang()
函数:

import lxml.etree as ET

root = ET.fromstring(xml)

print root.xpath('//alt[lang("fr")]')
作为奖励,它将具有适当的
lang()
语义,如大小写不敏感和对语言区域的精明(例如,
lang('en')
也适用于
xml:lang=“en-US”

不幸的是,您不能使用
lang()
来确定节点的语言。您需要找到第一个
xml:lang
祖先并使用它:

mylang = node.xpath('(ancestor-or-self::*/@xml:lang)[1]')
将它们放在一起,以匹配没有语言的节点:

tree.xpath('//alt[not((ancestor-or-self::*/@xml:lang)[1])]')
tree.xpath('//alt[not((ancestor-or-self::*/@xml:lang)[1])]')