Пересчитать XML дочерний элемент - PullRequest
2 голосов
/ 16 июня 2020

Используя python3 Я пытаюсь прочитать файл xml и пересчитать значения на основе атрибутов в элементе, а затем записать копию всего файла xml с новыми значениями.

Пример xml файл (около 10 тыс. Строк в полном файле):

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

Взять один элемент из примера 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" />

Для простоты скажем, что я хотел взять Значение элемента (63 в примере выше) и разделите на 2 (63/2 = 31,5). Затем, если ItemComponent элемента material_type = "Cloth" снова разделите на 2 (31,5 / 2 = 15,75). Наконец, округлите до целого числа, прежде чем обновлять значение и повторять для каждого элемента, а затем записывать новый обновленный файл xml.

Я пытался использовать Чтение, изменение и запись xml, но мог не получится ничего полезного.

1 Ответ

1 голос
/ 17 июня 2020

Вероятно, вы ищете что-то вроде этих строк:

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

Результатом будет ваше xml со значением атрибута Items/Item/@value, разделенным на 2 или 4, если необходимо, и округленным на math.ceil(). Поскольку все Items в вашем примере имеют cloth в качестве значения атрибута material_type, все они были разделены на 4 и округлены до:

16
44
63
...