使用lxml通过xpath定位修改带命名空间的jetty.xml指定属性值
解决方案
核心原因
调用find/findall返回空的核心原因是没有正确处理XML默认命名空间:jetty.xml的根节点一般都配置了Spring默认命名空间,不带前缀的元素默认都属于该命名空间,直接写//bean的XPath只能匹配无命名空间的bean节点,和实际节点不匹配。
完整实现代码
from lxml import etree # 加载目标jetty.xml文件 tree = etree.parse("jetty.xml") root = tree.getroot() # 命名空间映射:value要和你本地jetty.xml根节点<beans>的xmlns属性值完全一致 # 可打印根节点前500字符确认:print(etree.tostring(root, encoding='utf8').decode()[:500]) ns_map = { "beans": "http://www.springframework.org/schema/beans" } # 定位目标Bean节点,通过class属性过滤,不依赖索引 target_bean = root.xpath( "//beans:bean[@class='org.eclipse.jetty.webapp.WebAppContext']", namespaces=ns_map )[0] # 修改contextPath属性值 target_bean.xpath( "./beans:property[@name='contextPath']", namespaces=ns_map )[0].set("value", "/hawtio") # 修改resourceBase属性值 target_bean.xpath( "./beans:property[@name='resourceBase']", namespaces=ns_map )[0].set("value", "${activemq.home}/webapps/hawtio") # 保存修改后的文件,保留XML声明和格式 tree.write( "jetty.xml", encoding="utf-8", xml_declaration=True, pretty_print=True )
注意事项
- 优先使用
xpath()方法而非find()/findall():lxml的find系列方法仅支持XPath 1.0子集,兼容性更差,直接调用xpath()方法可以避免大部分语法不兼容问题 - 命名空间URI必须完全匹配:如果本地jetty.xml的根节点命名空间和示例中的不一致,必须替换为你文件中实际的URI
- 如果存在多个同class的bean节点,可以在XPath中追加其他属性过滤条件,比如
[@id='xxx'],避免匹配到错误节点
内容的提问来源于stack exchange,提问作者M4CHINE
相关产品推荐
相关产品推荐

