【问题标题】:Updating Python lxml etree subElement attributes with values stored in CSV file使用存储在 CSV 文件中的值更新 Python lxml etree subElement 属性
【发布时间】:2021-12-16 07:57:35
【问题描述】:

我是 Python 新手,我可能在这里忽略了一些东西,但我找不到解决方案。我的问题与此处提出的问题有相似之处,但由于它使用 Pandas,我无法为我的案例找到类似的解决方案:Updating LXML attributes with values stored in CSV file

如何从 CSV 的行中获取 subElement 属性,而不是将其写为常量?我的测试 CSV 看起来像这样:

Gruppering,Personnummer,Anstallningsnummer,From,Tom,Avtalstillhorighet,Pensionsalder,Anstallningstyp,Avslutsorsak
1967112912341,196711291234,1,2012-05-01,2012-05-31,PA03,65,H3,S7
1979041212341,197904121234,1,2011-03-01,2011-03-31,PA03,65,H3,S7
1979041212342,197904121234,2,2012-03-01,2012-03-31,PA03,65,H3,S7
1979041212343,197904121234,3,2013-03-01,2013-03-31,PA03,65,H3,S7
1977012912341,197701291234,1,2011-11-01,2011-11-30,PA03,65,H3,S7
1974040412341,197404041234,1,2011-03-01,2011-03-31,PA03,65,H3,S7
1988090712341,198809071234,1,2012-06-01,2012-06-30,PA03,65,H3,S7
1988090712342,198809071234,2,2013-06-01,2013-06-30,PA03,65,H3,S7

我的代码创建了一个如下所示的 XML:

<Arbetstagare Personnummer="Test">
    <Anstallning Anstallningsnummer="Test">
      <Period>
        <From>2012-05-01</From>
        <Tom>2012-05-31</Tom>
        <Avtalstillhorighet>PA03</Avtalstillhorighet>
        <Pensionsalder>65</Pensionsalder>
        <Anstallningstyp>H3</Anstallningstyp>
        <Avslutsorsak>S7</Avslutsorsak>
      </Period>
    </Anstallning>
  </Arbetstagare>

而不是 Personnummer="Test" 和 Anstallningsnummer="Test" 我希望属性值是 CSV 中行的第 2 列和第 3 列中的值。因此 XML 的前两行应为:

<Arbetstagare Personnummer="196711291234">
    <Anstallning Anstallningsnummer="1">

我的代码的相关部分如下所示:

from lxml import etree
from itertools import groupby
import csv

with open(r'\\ora-2.ug.test.se\utdata\Diverse filer\Öppna H3\Arbetsdokument\TestCSV.csv') as data_file:
    reader = csv.DictReader(data_file)
    f = lambda x: x['Gruppering']
    data = sorted(list(reader), key=f)

    root = etree.Element('root')
    for k, g in groupby(data, key=f):
        Personnummer = etree.SubElement(root, 'Arbetstagare', Personnummer='Test') 
        Anstallningsnummer = etree.SubElement(Personnummer, 'Anstallning', Anstallningsnummer='Test')

我想我必须使用 Personnummer.attrib["Personnummer"] = ???或 Personnummer.set(attr, value) 但如何从 CSV 中获取值?

【问题讨论】:

    标签: python csv lxml itertools elementtree


    【解决方案1】:

    在查阅了 DictReader 文档 here 之后,我会推荐如下内容:

    from lxml import etree
    from itertools import groupby
    import csv
    
    with open(r'TestCSV.csv') as data_file:
        reader = csv.DictReader(data_file)
        root = etree.Element('root')
        for row in sorted(reader, key=lambda x:x['Gruppering']):
            Personnummer = etree.SubElement(root, 'Arbetstagare', Personnummer=row['Personnummer'])
            Anstallningsnummer = etree.SubElement(Personnummer, 'Anstallning', Anstallningsnummer=row['Anstallningsnummer'])
            Period = etree.SubElement(Anstallningsnummer, 'Period')
            etree.SubElement(Period, 'From', ).text = row['From']
            etree.SubElement(Period, 'Tom', ).text = row['Tom']
            etree.SubElement(Period, 'Avtalstillhorighet', ).text = row['Avtalstillhorighet']
            etree.SubElement(Period, 'Pensionsalder', ).text = row['Pensionsalder']
            etree.SubElement(Period, 'Anstallningstyp', ).text = row['Anstallningstyp']
            etree.SubElement(Period, 'Avslutsorsak', ).text = row['Avslutsorsak']
    
    with open('testoutput.xml', 'wb') as f:
        f.write(etree.tostring(root))
    
    
    

    您的示例中的data 只是Python 字典的列表,每个字典中的信息都可以这样访问。

    您可能也在考虑如何按“Gruppering”进行分组,只需要按它排序即可。

    输出:

    <root>
        <Arbetstagare Personnummer="196711291234">
            <Anstallning Anstallningsnummer="1">
                <Period>
                    <From>2012-05-01</From>
                    <Tom>2012-05-31</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
        <Arbetstagare Personnummer="197404041234">
            <Anstallning Anstallningsnummer="1">
                <Period>
                    <From>2011-03-01</From>
                    <Tom>2011-03-31</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
        <Arbetstagare Personnummer="197701291234">
            <Anstallning Anstallningsnummer="1">
                <Period>
                    <From>2011-11-01</From>
                    <Tom>2011-11-30</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
        <Arbetstagare Personnummer="197904121234">
            <Anstallning Anstallningsnummer="1">
                <Period>
                    <From>2011-03-01</From>
                    <Tom>2011-03-31</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
        <Arbetstagare Personnummer="197904121234">
            <Anstallning Anstallningsnummer="2">
                <Period>
                    <From>2012-03-01</From>
                    <Tom>2012-03-31</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
        <Arbetstagare Personnummer="197904121234">
            <Anstallning Anstallningsnummer="3">
                <Period>
                    <From>2013-03-01</From>
                    <Tom>2013-03-31</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
        <Arbetstagare Personnummer="198809071234">
            <Anstallning Anstallningsnummer="1">
                <Period>
                    <From>2012-06-01</From>
                    <Tom>2012-06-30</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
        <Arbetstagare Personnummer="198809071234">
            <Anstallning Anstallningsnummer="2">
                <Period>
                    <From>2013-06-01</From>
                    <Tom>2013-06-30</Tom>
                    <Avtalstillhorighet>PA03</Avtalstillhorighet>
                    <Pensionsalder>65</Pensionsalder>
                    <Anstallningstyp>H3</Anstallningstyp>
                    <Avslutsorsak>S7</Avslutsorsak>
                </Period>
            </Anstallning>
        </Arbetstagare>
    </root>
    

    【讨论】:

    • 感谢@Forensic_07,它解决了问题的第一部分。但是我得到 NameError: name 'g' is not defined,因为在新代码中 G 不再定义。如何在保留新代码的同时定义 G?这是生成名称错误的代码。 Period = etree.SubElement(Anstallningsnummer, 'Period') for entry in g: Personnummer = etree.SubElement(Period, 'Personnummer') Anstallningsnummer = etree.SubElement(Period, 'Anstallningsnummer') Personnummer.text = entry[ 'Personnummer'] Anstallningsnummer.text = entry['Anstallningsnummer']
    • 这与我的第一个代码中出现的 itertools 和 groupby() 迭代器 (Documentation) 有关,但被排除在 Forensic_07 的建议之外
    • 你想用 groupby 完成什么?我不确定你是否需要它。
    • 已扩展答案以匹配我认为您的预期输出。
    • 非常感谢!那成功了。我还有很多东西要学!
    猜你喜欢
    • 2019-02-19
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 2019-03-11
    • 1970-01-01
    • 2020-08-28
    • 2016-04-03
    相关资源
    最近更新 更多