使用 python 和 lxml 修改带有命名空间的 xml 文件中的值

Modify a value in xml file with namespaces using python and lxml

Xml file:exercise.xml

<Configuration xmlns="http://totem.local/Pane/Configuration">
    <Types>         
        <Type name="F14_simpleGET" clazz="local.totem.zorg.priv.proc.F14.F14_simpleGET" ttl="3600" type="SYNC">
            <Param name="active_installation" value="true"/>
            <Param name="mode_beta" value="false"/>
        </Type>

        <Type name="F15_FixGET" clazz="local.totem.zorg.priv.proc.F15.F15_fixGET" ttl="3600" type="ASYNC">
            <Param name="context" value="Real"/>
            <Param name="Active" value="2"/>
            <Param name="Mode_gama" value="true"/>
        </Type>

    </Types>
    
</Configuration>

要求更改:

<Param name="mode_beta" value="false"/> to <Param name="mode_beta" value="true"/> 
<Param name="Mode_gama" value="true"/> to <Param name="Mode_gama" value="false"/>

使用一个使用 lxml 的小 python 脚本并将结果保存到 result.xml

请问如何做到这一点,我尝试了很多方法,但没有任何效果

这是我试过的东西

from lxml import etree as ET
tree = ET.parse('exercise.xml')
root = tree.getroot()


for val in tree.xpath("/Configuration/Types/Type[@name='F14_simpleGET']/Param[@name='mode_beta']"):
   val.attrib['value'] = 'true'


  
tree.write('result.xml')

由于您对任何其他方法持开放态度,我建议您使用 re(正则表达式)模块来更改 XML 文件:

import re
myXML = """
<Configuration xmlns="http://totem.local/Pane/Configuration">
    <Types>         
        <Type name="F14_simpleGET" clazz="local.totem.zorg.priv.proc.F14.F14_simpleGET ttl="3600" type="SYNC">
            <Param name="active_installation" value="true"/>
            <Param name="mode_beta" value="false"/>
        </Type>

        <Type name="F15_FixGET" clazz="local.totem.zorg.priv.proc.F15.F15_fixGET" ttl="3600" type="ASYNC">
            <Param name="context" value="Real"/>
            <Param name="Active" value="2"/>
            <Param name="Mode_gama" value="true"/>
        </Type>

    </Types>
    
</Configuration>
"""
modifiedXML = re.sub(r'\<Param name="mode_beta" value="false"\/>', '<Param name="mode_beta" value="true"/>' , myXML)
modifiedXML = re.sub(r'\<Param name="Mode_gama" value="true"\/>', '<Param name="Mode_gama" value="false"/>' , modifiedXML)
print(modifiedXML)

请注意,无论您是从 URL link、文件还是字符串读取文件,结果都是相同的:

<Configuration xmlns="http://totem.local/Pane/Configuration">
    <Types>         
        <Type name="F14_simpleGET" clazz="local.totem.zorg.priv.proc.F14.F14_simpleGET ttl="3600" type="SYNC">
            <Param name="active_installation" value="true"/>
            <Param name="mode_beta" value="true"/>
        </Type>

        <Type name="F15_FixGET" clazz="local.totem.zorg.priv.proc.F15.F15_fixGET" ttl="3600" type="ASYNC">
            <Param name="context" value="Real"/>
            <Param name="Active" value="2"/>
            <Param name="Mode_gama" value="false"/>
        </Type>

    </Types>
    
</Configuration>

您已接近最初的尝试。您只需要考虑默认命名空间。 (不过从你的问题和标签看来你已经明白了。)

在 lxml (see the docs) 中有几种不同的方法来解释命名空间。

我的首选方法是将名称空间 uri 绑定到前缀并在 xpath 中使用该前缀 (see the docs)。

示例(我编写了 tpc 前缀(基于 uri 中的图腾窗格配置);它可以是 shorter/longer/different)...

from lxml import etree

tree = etree.parse("exercise.xml")

ns = {"tpc": "http://totem.local/Pane/Configuration"}

for param in tree.xpath("/tpc:Configuration/tpc:Types/tpc:Type[@name='F14_simpleGET']/tpc:Param[@name='mode_beta']",
                        namespaces=ns):
    param.attrib['value'] = 'true'

for param in tree.xpath("/tpc:Configuration/tpc:Types/tpc:Type[@name='F15_FixGET']/tpc:Param[@name='Mode_gama']",
                        namespaces=ns):
    param.attrib['value'] = 'false'

tree.write("result.xml")