Python 如果dict.key等于同一父节点中的其他XML节点,则将ET.SubElement.text设置为dict.value
因此,我正在使用ElementTree创建一个新的子元素,其中新节点的文本应该是dict值,如果相应值的dict键等于同一父节点中另一个XML节点的文本 XML示例: Python代码现在: 预期成果:Python 如果dict.key等于同一父节点中的其他XML节点,则将ET.SubElement.text设置为dict.value,python,xml,elementtree,Python,Xml,Elementtree,因此,我正在使用ElementTree创建一个新的子元素,其中新节点的文本应该是dict值,如果相应值的dict键等于同一父节点中另一个XML节点的文本 XML示例: Python代码现在: 预期成果: abc 10012 def 20025 我试图将创建alternativeExportValue节点的for循环放入my\u函数中,但最终在newNode.text中得到了相同的值,或者陷入了无休止的循环中。 正如您在预期结果中所看到的,如果在同一个父代码< >代码> > < p> >
abc
10012
def
20025
我试图将创建
alternativeExportValue
节点的for循环放入my\u函数中,但最终在newNode.text中得到了相同的值,或者陷入了无休止的循环中。
正如您在预期结果中所看到的,如果在同一个父代码< >代码> > < p> >,我希望DIATE值作为新创建的节点的文本,如果它与
<代码> <代码>内文匹配。
- 读取/处理CSV数据。(您已经这样做了,但是考虑一下。这将使用第一行的键将值映射到DICT。)
- 处理每个
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的每一行!)
如果可以切换到,则可以使用稍微复杂一点的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")
*in-ElementTree有限。谢谢@Daniel Haley。我使用My_函数的想法是在//name[@id=“0”]
中查找匹配键的值。我尝试切换到lxml,但是aevs\u elem=tree.xpath(f)。//scale[names/name[@id='0']='{name}']/alternativeExportValues”)[0]
返回索引器:列表索引超出范围。这意味着xPath不存在。@Alecbalec-您也切换到DictReader了吗?如果不是,您可能正在处理CSV的第一行,而XPath由于name[@id='0']='name'
而失败。如果您不想切换到DictReader,您可以跳过CSV的第一行或使用try/except。如果您切换到DictReader,您的CSV或XML中一定有不同的内容,因为我用您的问题进行了测试,没有发现任何错误。首先,非常感谢!第一个问题是读取csv文件时的编码。在for循环中,我运行了print(row)
来查看输出,它返回了'\ufeffname':
而不是name:
。将编码更改为“utf-8-sig”
,事情看起来好多了。我取消了代码注释并添加了一个print(get.('value'))
查看.csv文件中的哪一行代码实际中断。快速查看后,很明显,xPath
是区分大小写的,这就是它返回索引器的原因:列表索引超出范围
@Alecbalec-啊,是的xPath肯定区分大小写。在XP中强制值为大写或小写是一种痛苦ath 1.0(这是lxml支持的),但我将更新我的lxml答案,使其不区分大小写。是的,幸运的是,只有几行字符在原始XML文件中是小写的,而在csv文件中是大写的。再次感谢。
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>
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")
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")