因此,我正在用ElementTree创建一个新的子元素,其中新节点的文本应为dict值,如果对应值的dict键等于同一父节点内另一个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>
name;value
abc;10012
def;20025
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
中创建my_Function
节点的for循环放入,但最终在newNode.text
中获得相同的值,或者陷入无限循环。
如预期结果所示,如果dict.value与同一父级<name id="0">
中的
<scale>
innerText匹配,我希望dict.value作为新创建的Node的文本。
答案 0 :(得分:1)
我不确定my_Function
应该做什么,但是请考虑以下逻辑:
scale
元素。alternativeExportValue
元素。name
属性值“ 0”的id
元素是否与当前的“名称”条目匹配。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 *,该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受限制。