【问题标题】:Python ElementTree find() using namespacesPython ElementTree find() 使用命名空间
【发布时间】:2019-04-30 12:55:31
【问题描述】:

我正在尝试使用 Python 的 ElementTree 来解析和修改 xml 文件。 XML 命名空间带来了混乱。我可以使用 findall 和 finditer 来获取所有服务器名称。但是,我无法让 xpath 查询找到特定的服务器。相反,find 只是带回了父元素。

我需要做的是通过“名称”或“机器”元素找到正确的服务器并修改“参数”。

<? xml version=’1.0’ encoding=’UTF-8’?>
<domain xmlns=”http://xmlns.oracle.com.weblogic/domain”>
  <server>
    <name>Server1-rma</name>
    <machine>server1</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
  <server>
    <name>Server2-rma</name>
    <machine>server2</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
  <server>
    <name>Server3-rma</name>
    <machine>server3</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
</domain>

我尝试了查询的各种迭代。但是,我是 XPath 的新手,一定是做错了什么:

失败: root + “ns0:server/[ns0:machine=’server2’]

失败: root + “ns0:server/ns0:[machine=’server2’]

失败: root + “ns0:server/[ns0:machine=ns0:’server2’]

示例代码:

import xml.etree.ElementTree as ET
namespace = {‘ns0’: ‘ http://xmlns.oracle.com.weblogic/domain’}

tree = ET.parse(‘config.xml’)
root = tree.getroot()
for item in root.find((root + “ns0:server/[ns0:machine=’server2’]), namespace)
    print(item.tag)


output:
{http://xmlns.oracle.com.weblogic/domain}server

我希望能够匹配“机器”元素并拉出父元素以访问正确的“参数”元素。

我是 xpath 和 elementtree 的初学者,所以我很肯定,我只是做错了事。我只是不确定是什么。任何帮助将不胜感激。

【问题讨论】:

  • 正确的 XPath 表达式是 /ns0:domain/ns0:server[ns0:machine='server2']谓词是同一位置步骤的一部分。另外,请注意 ElementTree 来自 xml.etree 模块有 limited support for XPath 1.0
  • 感谢您的回复和信息。

标签: python xml xpath xml-namespaces elementtree


【解决方案1】:

就像 Alejandro 在评论中提到的那样,ElementTree has limited support for XPath。这对于您尝试做的事情应该没有太大影响。如果您需要完整的 XPath 1.0 支持,consider lxml

但是,它也有一些其他的怪癖。其中之一是它将自己的命名空间前缀添加到您的默认命名空间。要保留默认命名空间,您必须使用 register_namespace() 注册它。

Alejandro 也是正确的,选择服务器的正确 XPath 应该是:

/ns0:domain/ns0:server[ns0:machine='server2']

但是,当您构建树(使用 ET.parse())或获取根(使用 getroot())时,上下文已经是 ns0:domain,因此该上下文中的 XPath 实际上是:

./ns0:server[ns0:machine='server2']

由于您想要更新服务器的 arguments,我们也可以将其添加到 XPath:

./ns0:server[ns0:machine='server2']/ns0:server-start/ns0:arguments

See here 了解有关 XPath 位置路径的更多信息。

这是一个完整的例子。 (我使用前缀 wl 而不是 ns0 只是为了表明前缀并不重要,只要它遵循 rules for namespace 前缀。)

XML 输入(test.xml;固定引号和 XML 声明,因此它将是 well-formed

<?xml version='1.0' encoding='UTF-8'?>
<domain xmlns="http://xmlns.oracle.com.weblogic/domain">
  <server>
    <name>Server1-rma</name>
    <machine>server1</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
  <server>
    <name>Server2-rma</name>
    <machine>server2</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
  <server>
    <name>Server3-rma</name>
    <machine>server3</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
</domain>

Python

import xml.etree.ElementTree as ET

tree = ET.parse("test.xml")

ns = {"wl": "http://xmlns.oracle.com.weblogic/domain"}

ET.register_namespace("", ns["wl"])

try:
    tree.find("./wl:server[wl:machine='server2']/wl:server-start/wl:arguments", namespaces=ns).text = "BAM!!!"
except AttributeError:
    print("Unable to find the correct server element.")

tree.write("output.xml", xml_declaration=True, encoding="UTF-8")

XML 输出 (output.xml)

<?xml version='1.0' encoding='UTF-8'?>
<domain xmlns="http://xmlns.oracle.com.weblogic/domain">
  <server>
    <name>Server1-rma</name>
    <machine>server1</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
  <server>
    <name>Server2-rma</name>
    <machine>server2</machine>
    <server-start>
      <arguments>BAM!!!</arguments>
    </server-start>
  </server>
  <server>
    <name>Server3-rma</name>
    <machine>server3</machine>
    <server-start>
      <arguments> -Xms4g</arguments>
    </server-start>
  </server>
</domain>

【讨论】:

  • 它工作!感谢您非常详尽的解释。这有助于向前发展。
  • 确实,很详细的回答。
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 2020-12-26
  • 2012-05-08
  • 2023-04-01
  • 2017-07-08
  • 2019-03-26
相关资源
最近更新 更多