【问题标题】:Getting specific elements attribute with lxml使用 lxml 获取特定元素属性
【发布时间】:2021-08-05 10:27:30
【问题描述】:

我有以下 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>

我需要更改属性&lt;property name="contextPath" value="/admin" /&gt;的值

<property name="resourceBase" value="${activemq.home}/webapps/admin" />

<property name="contextPath" value="/hawtio" />

<property name="resourceBase" value="${activemq.home}/webapps/hawtio" />

我也需要不使用索引来做,我需要使用 xpath 来做。

这意味着,我希望使用 xpath 来访问特定元素并更改其属性 不使用(例如)树[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() 返回 None 并运行 findall() 返回一个空列表,使用命名空间运行这些选项也返回空列表 \None

进一步说明 - 打开一个 xml 文件,找到特定元素并编辑它们的属性 NO MATTER 其索引(例如 myroot[0][2])并将更改写回文件。

干杯,

【问题讨论】:

标签: python xml lxml


【解决方案1】:

试试下面的(不使用外部库)

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>

【讨论】:

  • 早安秃头!感谢您的时间和回答,这确实有效,这是我为完成我的任务所做的工作 root = etree.fromstring(xml) prop = root.find('./property[@name="contextPath" ]') prop.attrib['value'] = '/hawtio' prop = root.find(('./property[@name="resourceBase"]')) prop.attrib['value'] = "${ activemq.home}/webapps/hawtio" etree.dump(root) 但是,我正在解析一个需要使用脚本编辑的实际 xml 文件。有没有办法像您的答案一样创建一个块并将该特定块应用于特定点的 xml 文件?
  • @M4CHINE 尝试对您的脚本采用我的解决方案。您需要做的就是解析文件,替换属性值(基于我的代码),保存文件。从这里控制。随意投票。
  • 也许我在你的解决方案中遗漏了一些东西,你能进一步解释一下吗?生病编辑帖子以解释我正在执行的步骤。
  • 我的代码找到名称为“contextPath”的属性,并将该值替换为另一个值。
【解决方案2】:

使用 baldermans 的答案,我找到了解决方法。

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 元素添加到文件中,我的解决方案就不是很好,如果您找到比我更好的解决方案,请发布。

编辑:

刚注意到文件更新了,这里是更新

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'

由于属性作为键值返回,我们可以使用内置的 dict itervalues() 函数来定位特定的键。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多