Recalculate XML child element

Viewed 33

Using python3 I am trying to read an xml file and recalculate values based on the attributes within the Item, then write a copy of entire xml file with new values.

Example of xml file (about 10k rows in full file):

<?xml version="1.0" encoding="utf-8"?>
<Items>
  <Item id="headscarf_d"
        name="{=wW3iouiU}Hijab"
        mesh="headscarf_d"
        culture="Culture.aserai"
        weight="0.5"
        value="63"
        appearance="1"
        Type="HeadArmor">
    <ItemComponent>
      <Armor head_armor="3"
             has_gender_variations="false"
             beard_cover_type="type3"
             hair_cover_type="all"
             modifier_group="cloth_unarmoured"
             material_type="Cloth"/>
    </ItemComponent>
    <Flags Civilian="true"
           UseTeamColor="true" />
  </Item>
  <Item id="open_head_scarf"
        name="{=qsVRoGUv}Open Head Scarf"
        mesh="aserai_helmet_c"
        culture="Culture.aserai"
        weight="0.6"
        value="174"
        appearance="1"
        Type="HeadArmor">
    <ItemComponent>
      <Armor head_armor="5"
             has_gender_variations="false"
             beard_cover_type="type3"
             hair_cover_type="all"
             modifier_group="cloth_unarmoured"
             material_type="Cloth"/>
    </ItemComponent>
    <Flags Civilian="true"
           UseTeamColor="true" />
  </Item>
  <Item id="woven_turban"
        name="{=ArPvuBYK}Woven Turban"
        subtype="head_armor"
        mesh="aserai_helmet_h"
        culture="Culture.aserai"
        weight="0.8"
        difficulty="0"
        value="250"
        appearance="1"
        Type="HeadArmor">
    <ItemComponent>
      <Armor head_armor="6"
             has_gender_variations="false"
             beard_cover_type="type2"
             hair_cover_type="all"
             modifier_group="cloth_unarmoured"
             material_type="Cloth"/>
    </ItemComponent>
    <Flags Civilian="true"
           UseTeamColor="true" />
  </Item>
</Items>

Taking a single item from the example xml,

<Item id="headscarf_d"
        name="{=wW3iouiU}Hijab"
        mesh="headscarf_d"
        culture="Culture.aserai"
        weight="0.5"
        value="63"
        appearance="1"
        Type="HeadArmor">
    <ItemComponent>
      <Armor head_armor="3"
             has_gender_variations="false"
             beard_cover_type="type3"
             hair_cover_type="all"
             modifier_group="cloth_unarmoured"
             material_type="Cloth"/>
    </ItemComponent>
    <Flags Civilian="true"
           UseTeamColor="true" />

For simplicity say I wanted to take the Item value (63 above example) and divide by 2 (63/2=31.5). Then if the Item's ItemComponent material_type="Cloth" divide by 2 again (31.5/2=15.75). Finally round to an integer before updating the value and repeating for each item then writing the new updated xml file.

I attempted to use Reading, modifying and writing xml but could not get anything useful.

1 Answers

You are probably looking for something along these lines:

from lxml import etree
import math

inv="""[your xml above]"""
doc = etree.XML(inv)

values = doc.xpath('//Item')
materials  = doc.xpath('Item//ItemComponent//Armor')
for t, m in zip(values,materials):
    if m.attrib['material_type'] == 'Cloth':
        val = float(t.attrib['value'])/4
        t.attrib['value'] = str(math.ceil(val))
    else:
        t.attrib['value']= str(math.ceil(val*2))
print(etree.tostring(doc).decode())

The output is your xml with the Items/Item/@value attribute value divided by 2 or 4, as necessary, and rounded up by math.ceil(). Since all Items in your example have cloth as the value of the attribute material_type, they were all divided by 4 and rounded up to:

16
44
63
Related