0

i have following xml file:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE TaskDefinition PUBLIC "xxx" "yyy">
<TaskDefinition created="time_stamp" formPath="path/sometask.xhtml" id="sample_id" modified="timestamp_b" name="sample_task" resultAction="Delete" subType="subtype_sample_task" type="sample_type">
  <Attributes>
    <Map>
      <entry key="applications" value="APP_NAME"/>
      <entry key="aaa" value="true"/>
      <entry key="bbb" value="true"/>
      <entry key="ccc" value="true"/>
      <entry key="ddd" value="true"/>
      <entry key="eee" value="Disabled"/>
      <entry key="fff"/>
      <entry key="ggg"/>
    </Map>
  </Attributes>
  <Description>Description.</Description>
  <Owner>
    <Reference class="sample_owner_class" id="sample_owner_id" name="sample__owner_name"/>
  </Owner>
  <Parent>
    <Reference class="sample_parent_class" id="sample_parent_id" name="sample_parent_name"/>
  </Parent>
</TaskDefinition>

I want to search for: <entry key="applications" value="APP_NAME"/>

and change the value to ie.: `APP_NAME_2.

I know i can extract this value by this:

import xml.etree.cElementTree as ET

tree = ET.ElementTree(file='sample.xml')
root = tree.getroot()

print(root[0][0][0].tag, root[0][0][0].attrib)

but in this case i have to know exact position of ths entry in tree - so it is not flexible, and i have no idea how to change it.

Also tried something like this:

for app in root.attrib:
    if 'applications' in root.attrib:
        print(app)

but i can't figure out, why this returns nothing.

In python docs, there is following example:

for rank in root.iter('rank'):
    new_rank = int(rank.text) + 1
    rank.text = str(new_rank)
    rank.set('updated', 'yes')    
tree.write('output.xml')

but i have no idea how to addjust this to my example. I don't want to use regex for this case. Any help appreciated.

Bellerofont
  • 1,081
  • 18
  • 17
  • 16
Fangir
  • 131
  • 6
  • 16

1 Answers1

2

You can locate the specific entry element with XPath.

import xml.etree.ElementTree as ET

tree = ET.parse("sample.xml")   

# Find the element that has a 'key' attribute with a value of 'applications'
entry = tree.find(".//entry[@key='applications']")

# Change the value of the 'value' attribute
entry.set("value", "APP_NAME_2")

tree.write("output.xml")

Result (output.xml):

<TaskDefinition created="time_stamp" formPath="path/sometask.xhtml" id="sample_id" modified="timestamp_b" name="sample_task" resultAction="Delete" subType="subtype_sample_task" type="sample_type">
  <Attributes>
    <Map>
      <entry key="applications" value="APP_NAME_2" />
      <entry key="aaa" value="true"/>
      <entry key="bbb" value="true"/>
      <entry key="ccc" value="true"/>
      <entry key="ddd" value="true"/>
      <entry key="eee" value="Disabled"/>
      <entry key="fff"/>
      <entry key="ggg"/>
    </Map>
  </Attributes>
  <Description>Description.</Description>
  <Owner>
    <Reference class="sample_owner_class" id="sample_owner_id" name="sample__owner_name"/>
  </Owner>
  <Parent>
    <Reference class="sample_parent_class" id="sample_parent_id" name="sample_parent_name"/>
  </Parent>
</TaskDefinition>
mzjn
  • 48,958
  • 13
  • 128
  • 248
  • This is excatly what i want, now it looks so simple... When i try to `print(entry)`, i get `` - is that possible to get "normal value" ? – Fangir Jan 26 '17 at 10:54
  • Perhaps it is `print(entry.tag)` that you want? – mzjn Jan 26 '17 at 11:20
  • `entry.text` will be empty since the element has no content. – mzjn Jan 26 '17 at 11:21
  • right now, i noticed, that xml definition and !DOCTYPE are missing. I handled xml declaration, but can't get over with !DOCTYPE. Is there any way to preserve it? – Fangir Mar 15 '17 at 09:18
  • Perhaps this will work for you: http://stackoverflow.com/a/8868551/407651. If it does not help, I suggest that you post a new question. – mzjn Mar 15 '17 at 10:19