【问题标题】:How to iterate through Elementtree using namespaces如何使用命名空间遍历 Elementtree
【发布时间】:2018-10-04 19:37:43
【问题描述】:

我一直在尝试使用 Python 中的 ElementTree 解析 xml 文档以修改其中一个元素,但是由于命名空间,我一直遇到问题。

我可以从我的 xml 文档中获取所有标签

data = open('query-user-by-name.xml').read()
root = ET.fromstring(data)
for item in root.iter():
    print(item.tag)

这给了我:

{http://prism.evolveum.com/xml/ns/public/query-3}query
{http://prism.evolveum.com/xml/ns/public/query-3}filter
{http://prism.evolveum.com/xml/ns/public/query-3}equal
{http://prism.evolveum.com/xml/ns/public/query-3}matching
{http://prism.evolveum.com/xml/ns/public/query-3}path
{http://prism.evolveum.com/xml/ns/public/query-3}value

我创建了一个带有命名空间的字典:

namespaces = {'ns':'http://prism.evolveum.com/xml/ns/public/query-3'}

但是当我尝试使用

找到我正在搜索的元素时
data = open('query-user-by-name.xml').read()
root = ET.fromstring(data)
for item in root.iter('ns:value', namespaces):
    print(item.tag)

我得到错误:

TypeError: iter() 最多接受 2 个参数(给定 3 个)

似乎我只给出了两个论点而不是三个论点。使用命名空间正确遍历这些元素我做错了什么?

*编辑:这是我的 query-all-users.xml 文件:

<query xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
        xmlns="http://prism.evolveum.com/xml/ns/public/query-3">
<filter>
        <equal>
        <matching>polyStringNorm</matching>
                <path>c:name</path>
                <value>lilpotter</value>
        </equal>
</filter>
</query>

【问题讨论】:

  • iter() 是一个方法,所有方法都默认通过实例引用(通常命名为self)。将消息视为 "iter() takes at most 1 argument + instance reference (2 + instance given)"
  • iter 被记录为仅采用一个参数(超出实例引用):tag docs.python.org/3.5/library/… 也许尝试使用iterfind,它采用额外的namespaces 参数?

标签: python xml parsing elementtree


【解决方案1】:

按照@gill Hamilton 的建议,您应该使用iterfind,但要使用XPath 表达式,例如:“.//ns:value”。

这是一个完整的例子:

import xml.etree.ElementTree as ET

content = u"""\
<query xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
        xmlns="http://prism.evolveum.com/xml/ns/public/query-3">
<filter>
        <equal>
        <matching>polyStringNorm</matching>
                <path>c:name</path>
                <value>lilpotter</value>
        </equal>
</filter>
</query>"""

root = ET.fromstring(content)

NS = {'ns': 'http://prism.evolveum.com/xml/ns/public/query-3'}

for item in root.iterfind(".//ns:value", NS):
    print(item.tag)

# -> {http://prism.evolveum.com/xml/ns/public/query-3}value

【讨论】:

  • 当我尝试它时似乎没有返回任何东西。
  • iterfind 似乎没有找到任何东西,但是我可以通过包含如下命名空间来找到我正在寻找的元素:for item in root.iter('{http://prism.evolveum.com/xml/ns/public/query-3}value'): print(item.tag) 但我不知道如何找到它使用命名空间字典。
  • 你能发布一个“query-user-by-name.xml”的样本吗?
  • 是的@Laurent,我已将其添加到我的问题中,谢谢。
  • 其实你需要使用XPath表达式,比如“.//ns:value”。查看我的编辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
相关资源
最近更新 更多