python elementtree 命名空间_使用名称空间的Python ElementTree find()

I am attempting to use Python’s ElementTree to parse and modify an xml file. The confusion comes with the XML Namespace. I can use the findall and finditer to get all of the servers names. However, I can't get the xpath query to work to find a specific server. instead the find just brings back the parent element.

What I need to do is find the correct server by the “name” or “machine” element and modify the “arguments”.

xml version=’1.0’ encoding=’UTF-8’?>

Server1-rma

server1

-Xms4g

Server2-rma

server2

-Xms4g

Server3-rma

server3

-Xms4g

I have attempted various iterations of the query. However, I am new to XPath and must be doing something wrong:

Failed:

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

Failed:

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

Failed:

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

sample code:

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

I was hoping be able to match the "machine" element and pull the parent element in order to access the correct "arguments" element.

I am a beginner at xpath and elementtree so I am positive, that I am just doing something incorrectly. I am just not sure what. Any help would be greatly appreciated.

解决方案

Like Alejandro mentioned in a comment, 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.

However, it also has some other quirks. One of them is that it will add it's own namespace prefix to your default namespace. To keep the default namespace you'll have to register it with register_namespace().

Alejandro is also correct that the correct XPath to select the server would be:

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

However, when you build the tree (with ET.parse()) or get the root (with getroot()), the context is already ns0:domain so the XPath in that context would actually be:

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

Since you're wanting to update the arguments of the server, we can add that to the XPath too:

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

See here for more info on XPath location paths.

Here's a full example. (I'm using the prefix wl instead of ns0 just to show that the prefix doesn't really matter as long as it follows the rules for namespace prefixes.)

XML Input (test.xml; fixed quotes and XML declaration so it would be well-formed)

Server1-rma

server1

-Xms4g

Server2-rma

server2

-Xms4g

Server3-rma

server3

-Xms4g

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 (output.xml)

Server1-rma

server1

-Xms4g

Server2-rma

server2

BAM!!!

Server3-rma

server3

-Xms4g

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值