使用 lxml 获取特定元素属性
Getting specific elements attribute with lxml
我有以下 xml 文件,我需要到达特定块并更改 2 个属性值。
xml 文件 - https://alvinalexander.com/java/jwarehouse/activemq/assembly/src/release/conf/jetty.xml.shtml
我在本地有。
我需要编辑的块:
<bean class="org.eclipse.jetty.webapp.WebAppContext">
<property name="contextPath" value="/admin" />
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
<property name="logUrlOnStart" value="true" />
</bean>
我需要更改属性值<property name="contextPath" value="/admin" />
和
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
至
<property name="contextPath" value="/hawtio" />
和
<property name="resourceBase" value="${activemq.home}/webapps/hawtio" />
我还需要不使用索引来做,我需要使用 xpath 来做。
这意味着,我希望使用 xpath 到达特定元素并更改其属性
不使用(例如)tree[i]
我的 python 代码(或至少我希望做的)
import lxml
from lxml import etree
#Initialise xml file , xml file has namespaces
tree = etree.parse("jetty.xml")
myroot = tree.getroot()
#XML File has atleast 5 childs to each element
#From here i expect to edit attributes without using
#Manual indexing , for example
#prop = myroot.find('property[@name="contextPath"]')
#prop.attrib['value'] = '/hawtio'
#prop = myroot.find(('./property[@name="resourceBase"]'))
#prop.attrib['value'] = "${activemq.home}/webapps/hawtio"
#etree.write("jetty.xml", pretty_print=True)
同样,我正在解析一个包含命名空间和大量子元素的文件,运行 find()
returns None 和 运行 findall()
returns 一个空列表,运行 那些带有命名空间的选项也 returns 空列表 \ None
进一步解释 - 打开一个 xml 文件,找到特定元素并编辑它们的属性 NO MATTER 它们的索引(例如 myroot[0][2])和将更改写回文件。
干杯,
试试下面的方法(没有使用外部库)
import xml.etree.ElementTree as ET
xml = '''<bean class="org.eclipse.jetty.webapp.WebAppContext">
<property name="contextPath" value="/admin" />
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
<property name="logUrlOnStart" value="true" />
</bean>'''
root = ET.fromstring(xml)
prop = root.find('./property[@name="contextPath"]')
prop.attrib['value'] = 'new_value_goes_here'
ET.dump(root)
输出
<bean class="org.eclipse.jetty.webapp.WebAppContext">
<property name="contextPath" value="new_value_goes_here" />
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
<property name="logUrlOnStart" value="true" />
</bean>
使用 baldermans answer 我找到了解决方法。
import lxml
from lxml import etree
#Initialise xml file
tree = etree.parse("jetty.xml")
myroot = tree.getroot()
test = myroot.find('.//*[@name="contextPath"]')
print(test)
产量:
Element {http://www.springframework.org/schema/beans}property at
获取属性:
print(test.attrib)
{'name': 'contextPath', 'value': '/admin'}
更改值:
prop = myroot.find('.//*[@name="contextPath"]')
prop.attrib['value'] = '/hawtio'
prop = myroot.find(('.//*[@name="resourceBase"]'))
prop.attrib['value'] = "${activemq.home}/webapps/hawtio"
etree.write("jetty.xml", pretty_print=True)
我在 find()
和 [@name="contextPath"]
上使用了 .//*
选项
因为我知道元素 contextPath
只出现过一次
因此,如果将来在文件中添加另一个 contextPath 元素,我的解决方案就不是很好,如果您找到比我更好的解决方案,请 post 它。
编辑:
刚刚注意到文件已更新,这里是更新
prop = myroot.findall('.//*[@name="contextPath"]')
for i in prop:
if '/admin' in i.attrib.itervalues():
prop.attrib['value'] = '/hawtio'
prop = myroot.findall(('.//*[@name="resourceBase"]'))
for i in prop:
if '${activemq.home}/webapps/admin' in i.attrib.itervalues():
prop.attrib['value'] = '${activemq.home}/webapps/hawtio'
由于属性作为键值返回,我们可以使用内置字典 itervalues()
函数来定位特定键。
我有以下 xml 文件,我需要到达特定块并更改 2 个属性值。
xml 文件 - https://alvinalexander.com/java/jwarehouse/activemq/assembly/src/release/conf/jetty.xml.shtml
我在本地有。
我需要编辑的块:
<bean class="org.eclipse.jetty.webapp.WebAppContext">
<property name="contextPath" value="/admin" />
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
<property name="logUrlOnStart" value="true" />
</bean>
我需要更改属性值<property name="contextPath" value="/admin" />
和
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
至
<property name="contextPath" value="/hawtio" />
和
<property name="resourceBase" value="${activemq.home}/webapps/hawtio" />
我还需要不使用索引来做,我需要使用 xpath 来做。
这意味着,我希望使用 xpath 到达特定元素并更改其属性 不使用(例如)tree[i]
我的 python 代码(或至少我希望做的)
import lxml
from lxml import etree
#Initialise xml file , xml file has namespaces
tree = etree.parse("jetty.xml")
myroot = tree.getroot()
#XML File has atleast 5 childs to each element
#From here i expect to edit attributes without using
#Manual indexing , for example
#prop = myroot.find('property[@name="contextPath"]')
#prop.attrib['value'] = '/hawtio'
#prop = myroot.find(('./property[@name="resourceBase"]'))
#prop.attrib['value'] = "${activemq.home}/webapps/hawtio"
#etree.write("jetty.xml", pretty_print=True)
同样,我正在解析一个包含命名空间和大量子元素的文件,运行 find()
returns None 和 运行 findall()
returns 一个空列表,运行 那些带有命名空间的选项也 returns 空列表 \ None
进一步解释 - 打开一个 xml 文件,找到特定元素并编辑它们的属性 NO MATTER 它们的索引(例如 myroot[0][2])和将更改写回文件。
干杯,
试试下面的方法(没有使用外部库)
import xml.etree.ElementTree as ET
xml = '''<bean class="org.eclipse.jetty.webapp.WebAppContext">
<property name="contextPath" value="/admin" />
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
<property name="logUrlOnStart" value="true" />
</bean>'''
root = ET.fromstring(xml)
prop = root.find('./property[@name="contextPath"]')
prop.attrib['value'] = 'new_value_goes_here'
ET.dump(root)
输出
<bean class="org.eclipse.jetty.webapp.WebAppContext">
<property name="contextPath" value="new_value_goes_here" />
<property name="resourceBase" value="${activemq.home}/webapps/admin" />
<property name="logUrlOnStart" value="true" />
</bean>
使用 baldermans answer 我找到了解决方法。
import lxml
from lxml import etree
#Initialise xml file
tree = etree.parse("jetty.xml")
myroot = tree.getroot()
test = myroot.find('.//*[@name="contextPath"]')
print(test)
产量:
Element {http://www.springframework.org/schema/beans}property at
获取属性:
print(test.attrib)
{'name': 'contextPath', 'value': '/admin'}
更改值:
prop = myroot.find('.//*[@name="contextPath"]')
prop.attrib['value'] = '/hawtio'
prop = myroot.find(('.//*[@name="resourceBase"]'))
prop.attrib['value'] = "${activemq.home}/webapps/hawtio"
etree.write("jetty.xml", pretty_print=True)
我在 find()
和 [@name="contextPath"]
上使用了 .//*
选项
因为我知道元素 contextPath
只出现过一次
因此,如果将来在文件中添加另一个 contextPath 元素,我的解决方案就不是很好,如果您找到比我更好的解决方案,请 post 它。
编辑:
刚刚注意到文件已更新,这里是更新
prop = myroot.findall('.//*[@name="contextPath"]')
for i in prop:
if '/admin' in i.attrib.itervalues():
prop.attrib['value'] = '/hawtio'
prop = myroot.findall(('.//*[@name="resourceBase"]'))
for i in prop:
if '${activemq.home}/webapps/admin' in i.attrib.itervalues():
prop.attrib['value'] = '${activemq.home}/webapps/hawtio'
由于属性作为键值返回,我们可以使用内置字典 itervalues()
函数来定位特定键。