2

I have this complex xml file and we need to dynamically update some elements in it. I have successfully been able to update value strings (attributes) using lxml, but I'm completely unsure how to go about replacing an entire element. Here's some pseudo-code to show what I'm trying to do. import os from lxml import etree

directory_name = "C:\\apps"
file_name = "web.config"

xpath_identifier = '/configuration/applicationSettings/Things/setting[@name="CorsTrustedOrigins"]'

#contents of the xml file for reference:
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="Things" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
    </sectionGroup>
  </configSections>
  <appSettings/>   
  <applicationSettings>
    <Things>
      <setting name="CorsTrustedOrigins" serializeAs="Xml">
        <value>
          <ArrayOfString>
           <string>http://localhost:51363</string>
           <string>http://localhost:3333</string>
          </ArrayOfString>
        </value>
      </setting>
    </Things>
  </applicationSettings>
</configuration>

file_full_path = os.path.join(directory_name, file_name)
tree = etree.parse(file_full_path)
root = tree.getroot()

etree.tostring(root)


xpath_identifier = str(xpath_identifier)

value = root.xpath(xpath_identifier)

#This successfully prints the element I'm after, so I'm sure my xpath is good:
etree.tostring(value[0])

#This is the new xml element I want to replace the current xpath'ed element with:
newxml = '''
<setting name="CorsTrustedOrigins" serializeAs="Xml">
        <value>
          <ArrayOfString>
            <string>http://maddafakka</string>
          </ArrayOfString>
        </value>
      </setting>
'''

newtree = etree.fromstring(newxml)

#I've tried this:
value[0].getparent().replace(value[0], newtree)

#and this
value[0] = newtree

#The value of value[0] gets updated, but the "root document" does not.

What I'm trying to do is to update the "ArrayofStrings" element to reflect the values in the "newxml" var.

I'm kindof struggling to navigate the lxml infos on the web, but I can't seem to find an example similar to what I'm trying to do.

Any pointers appreciated!

4
  • 1
    what is the source XML and desired XML output? Commented Jan 19, 2017 at 13:08
  • Use XPath's sibling, XSLT, designed to transform full XML documents. And lxml can run both. Please post full XML source. Commented Jan 19, 2017 at 14:36
  • The only thing I see different is the string links no different element. Do you plan to have more than one link? Commented Jan 20, 2017 at 0:10
  • Possible duplicate of How can one replace an element in lxml? Commented Jun 20, 2017 at 19:31

1 Answer 1

2

You should just remove the indexed access on the node:

value[0].getparent().replace(value[0], newtree)

.... to: value.getparent().replace(value, newtree)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.