Python ElementTree Find() Using Namespaces
Solution 1:
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)
<?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 (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>
Post a Comment for "Python ElementTree Find() Using Namespaces"