Python ElementTree find() 使用命名空间
Python ElementTree find() using namespaces
我正在尝试使用 Python 的 ElementTree 来解析和修改 xml 文件。 XML 命名空间带来了混乱。我可以使用 findall 和 finditer 获取所有服务器名称。但是,我无法使用 xpath 查询来查找特定服务器。相反,查找只是带回父元素。
我需要做的是通过“name”或“machine”元素找到正确的服务器并修改“arguments”。
<? 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
我希望能够匹配 "machine" 元素并拉取父元素以访问正确的 "arguments" 元素。
我是 xpath 和 elementtree 的初学者,所以我很肯定,我只是做错了什么。我只是不确定是什么。任何帮助将不胜感激。
就像 Alejandro 在评论中提到的那样,ElementTree has limited support for XPath. That shouldn't matter too much for what you're trying to do. If you need full XPath 1.0 support, consider lxml。
然而,它还有一些其他的怪癖。其中之一是它将自己的名称空间前缀添加到您的默认名称空间。要保留默认命名空间,您必须使用 register_namespace().
注册它
Alejandro 也是正确的 select 服务器的正确 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>
我正在尝试使用 Python 的 ElementTree 来解析和修改 xml 文件。 XML 命名空间带来了混乱。我可以使用 findall 和 finditer 获取所有服务器名称。但是,我无法使用 xpath 查询来查找特定服务器。相反,查找只是带回父元素。
我需要做的是通过“name”或“machine”元素找到正确的服务器并修改“arguments”。
<? 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
我希望能够匹配 "machine" 元素并拉取父元素以访问正确的 "arguments" 元素。
我是 xpath 和 elementtree 的初学者,所以我很肯定,我只是做错了什么。我只是不确定是什么。任何帮助将不胜感激。
就像 Alejandro 在评论中提到的那样,ElementTree has limited support for XPath. That shouldn't matter too much for what you're trying to do. If you need full XPath 1.0 support, consider lxml。
然而,它还有一些其他的怪癖。其中之一是它将自己的名称空间前缀添加到您的默认名称空间。要保留默认命名空间,您必须使用 register_namespace().
注册它Alejandro 也是正确的 select 服务器的正确 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>