如果 dict.key 等于同一父节点中的其他 XML 节点,则将 ET.SubElement.text 设置为 dict.value

Set ET.SubElement.text to dict.value if dict.key equals other XML node within same parent

因此,我正在使用 ElementTree 创建一个新的子元素,其中新节点的文本应该是字典值,如果相应值的字典键等于同一父节点中另一个 XML 节点的文本节点

XML 示例:

<ns0:scaleType xmlns:ns0="http://someURL.com/">
  <scales>
    <scale>
        <names>
            <name id="0">abc</name>
            <name id="1" />
        </names>
        <alternativeExportValues>
        </alternativeExportValues>
    </scale>
    <scale>
        <names>
            <name id="0">def</name>
            <name id="1" />
        </names>
        <alternativeExportValues>
        </alternativeExportValues>
    </scale>
 </scales>
</ns0:scaleType>

CSV 示例:

name;value
abc;10012
def;20025

Python 现在代码:

import xml.etree.ElementTree as ET

import csv

csvData = []

with open('myCSV.csv', 'r', encoding="utf8") as f:
    reader = csv.reader(f, delimiter=";")
    for row in reader:
        csvData.append({'name': row[0], 'value': row[1]})

tree = ET.parse('myXml.xml')
root = tree.getroot()

def my_Function():
    for p in csvData:
        for name in root.findall(".//name[@id='0']"):
            text = name.text
            if p['name'] == text:
                value = p['value']
                return value
my_Function()


for elem in root.iter('alternativeExportValues'):
    newNode = ET.SubElement(elem, 'alternativeExportValue')
    newNode.text = 

tree.write("myNewXML.xml", encoding="utf-8")

预期结果:

<ns0:scaleType xmlns:ns0="http://someURL.com/">
  <scales>
    <scale>
        <names>
            <name id="0">abc</name>
            <name id="1" />
        </names>
        <alternativeExportValues>
           <alternativeExportValue>10012</alternativeExportValue>
        </alternativeExportValues>
    </scale>
    <scale>
        <names>
            <name id="0">def</name>
            <name id="1" />
        </names>
        <alternativeExportValues>
           <alternativeExportValue>20025</alternativeExportValue>
        </alternativeExportValues>
    </scale>
 </scales>
</ns0:scaleType>


我试图将创建 alternativeExportValue 节点的 for 循环放在 my_Function 中,但最终在 newNode.text 中得到相同的值或陷入无限循环。

正如您在预期结果中看到的那样,我希望 dict.value 作为新创建节点的文本,如果它与同一父 <scale> 中的
<name id="0"> innerText 匹配。

我不确定 my_Function 应该做什么,但请考虑以下逻辑:

  • Read/process CSV 数据。 (您已经在这样做了,但请考虑 DictReader。这将使用第一行中的键将值映射到字典。)
  • 处理每个 scale 个元素。
  • 使用 "value" 值创建一个新的 alternativeExportValue 元素。
  • 检查具有 id 属性值“0”的 name 元素是否与当前 "name" 条目匹配。
  • 如果是,附加新的 alternativeExportValue 元素。

示例...

import xml.etree.ElementTree as ET
import csv

with open('myCSV.csv', 'r', encoding="utf8") as csvfile:
    tree = ET.parse('myXml.xml')

    for row in csv.DictReader(csvfile, delimiter=";"):
        name = row.get("name")
        new_aev_elem = ET.Element("alternativeExportValue")
        new_aev_elem.text = row.get("value")
        for scale in tree.findall(".//scale"):
            name0 = scale.find("names/name[@id='0']")
            if name0.text == name:
                aevs_elem = scale.find("alternativeExportValues")
                aevs_elem.append(new_aev_elem)
                break

    tree.write("myNewXML.xml", encoding="utf-8")

这行得通,但效率不高,因为您必须处理要修改的实际 scale 元素之前的每个 scale 元素。

更糟糕的是,如果您删除 break,它将处理 XML 中的每个 scale 元素(对于 CSV 的每一行!)。

如果可以切换到 lxml,则可以使用稍微复杂一点的 XPath*,它只会处理需要修改的 scale 元素...

from lxml import etree
import csv

with open('myCSV.csv', 'r', encoding="utf8") as csvfile:
    tree = etree.parse('myXml.xml')

    uc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    lc = "abcdefghijklmnopqrstuvwxyz"

    for row in csv.DictReader(csvfile, delimiter=";"):
        name = row.get("name").lower()
        new_aev_elem = etree.Element("alternativeExportValue")
        new_aev_elem.text = row.get("value")
        aevs_elem = tree.xpath(f".//scale[translate(names/name[@id='0'],'{uc}','{lc}')='{name}']/alternativeExportValues")[0]
        aevs_elem.append(new_aev_elem)

    tree.write("myNewXML.xml", encoding="utf-8")

*ElementTree中的XPath support是有限的