简体   繁体   中英

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>

It's asked to change:

<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"/>

With a small python script that uses lxml and save the result to result.xml

Please How to do this, Ive tried many things but nothing works

Here something I've tried

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')

Since you are open to any other method, I suggest you use re (regex) module in order to make change in your XML file:

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)

Note that it won't matter whether you're reading the file from a URL link, a file or even a string, the result would be the same for all:

<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>

You were close with your original attempt. You just needed to account for the default namespace. (It seems from your question and tagging that you already figured that out though.)

There are a couple of different ways to account for namespaces in lxml ( see the docs ).

My preferred way is to bind the namespace uri to a prefix and use the prefix in the xpath ( see the docs ).

Example (I made up the tpc prefix (based on Totem Pane Configuration from the uri); it could be 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")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM