我正在尝试使用Python的ElementTree来解析和修改xml文件。 XML命名空间带来了混乱。我可以使用findall和finditer来获取所有服务器名称。但是,我无法使xpath查询工作来查找特定的服务器。取而代之的是,查找只是带回父元素。
我需要做的是通过“名称”或“机器”元素找到正确的服务器,然后修改“参数”。
<? 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的初学者,所以我很肯定自己只是在做一些错误的事情。我只是不确定。任何帮助将不胜感激。
答案 0 :(得分:1)
像亚历杭德罗(Alejandro)在评论ElementTree has limited support for XPath中提到的那样。对于您要执行的操作来说,这并不重要。如果需要全面的XPath 1.0支持,请consider lxml。
但是,它也有其他一些怪癖。其中之一就是它将自己的名称空间前缀添加到默认名称空间。要保留默认名称空间,您必须向register_namespace()注册它。
Alejandro还正确地选择了用于选择服务器的正确XPath:
ET.parse()
但是,当您使用getroot()
构建树或使用ns0:domain
获取根时,上下文已经为./ns0:server[ns0:machine='server2']
,因此该上下文中的XPath实际上是:
arguments
由于您要更新服务器的./ns0:server[ns0:machine='server2']/ns0:server-start/ns0:arguments
,因此我们也可以将其添加到XPath:
wl
See here有关XPath位置路径的更多信息。
这是一个完整的例子。 (我使用的是前缀ns0
而不是<?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>
,只是为了表明前缀在rules for namespace前缀之后并没有关系。)
XML输入(test.xml;固定引号和XML声明,因此为well-formed)
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")
Python
<?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>
XML输出(output.xml)
Failure/Error: response = Facebook.oauth_for_app(provider).exchange_access_token_info(token)
Koala::Facebook::OAuthTokenRequestError:
type: OAuthException, code: 190, message: Invalid OAuth access token. [HTTP 400]