4

我正在使用 python 2.7 并尝试解析下面的 XML - 我想要做的是创建一个包含所有类型的 python 数组,其中包含一个语言属性以及一个没有语言属性的数组。

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

我知道我可以通过语法找到语言属性为“fr”语言的 XML 部分:

树=ET.ElementTree(文件='popups.xml')
根 = 树.getroot()
对于 x in root.findall('alt[@{http://www.w3.org/XML/1998/namespace}lang="fr"]/alt'):
   打印 x.text

我真的不明白为什么我不能使用xml:lang而不是{http://www.w3.org/XML/1998/namespace}lang,但以上似乎适用于 Ubuntu 12.04

我试图找出的是“非”语法——XML 部分没有任何语言属性

有人对如何实现这一目标有任何想法吗?

<genre>
  <alt>
        <alt genre="easy listening">lounge</alt>
        <alt genre="alternative">ska</alt>
  </alt>

  <alt xml:lang="fr">
        <alt genre="gospel">catholique</alt>
  </alt>
</genre>
4

2 回答 2

4

您需要在 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:lang指定此属性的值由包含它的所有内容继承,类似于xml:basexmlns命名空间声明。因此,作为替代方案,我们可以在所有元素上显式设置语言:

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))

如果您愿意使用lxml,那么您对“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])]')
于 2013-01-09T23:02:55.473 回答
1

我真的不明白为什么我不能使用 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)我以前不熟悉的语法,但是 Google 搜索“没有属性的 xpath 查找元素”非常有用。

于 2013-01-09T22:44:42.150 回答