Python解析嵌套XML并展平数据

时间:2013-01-15 02:02:48

标签: python xml xml-parsing python-2.7 lxml

我正在尝试将以下XML数据压缩为CSV类型表数据。

我可以获取Sal元素及其属性中的数据,但我无法将SalC数据压缩为父航行属性以生成平面数据。

我想在XML数据下面展平,以便我可以写入数据库进行进一步处理。

col1,col2,col3,col4,col5,col6,col6,col7,col8,col9,col10

XML数据:

<Sal col1="a1" col2="C" col3="12/5/2012" col4="a" col5="8" col6="True">
    <SalC col7="A" col8="1" col9="2" col10="True"/>
    <SalC col7="A1" col8="1" col9="2" col10="False"/>
    <SalC col7="B" col8="1" col9="2" col10="False"/>
    <SalC col7="C" col8="1" col9="2" col10="False"/>
    <SalC col7="D" col8="1" col9="2" col10="False"/>
    <SalC col7="E" col8="1" col9="2" col10="False"/>
    <SalC col7="E1" col8="1" col9="2" col10="False"/>
    <SalC col7="F" col8="1" col9="2" col10="False"/>
</Sal>
<Sal col1="a1" col2="C" col3="12/9/2012" col4="b" col5="8" col6="True">
    <SalC col7="A" col8="1" col9="2" col10="False"/>
    <SalC col7="B" col8="1" col9="2" col10="False"/>
    <SalC col7="C" col8="1" col9="2" col10="True"/>
    <SalC col7="D" col8="1" col9="2" col10="False"/>
    <SalC col7="E" col8="1" col9="2" col10="False"/>
</Sal>
<Sal col1="a2" col2="C" col3="12/8/2012" col4="c" col5="15" col6="True">
    <SalC col7="A" col8="1" col9="2" col10="True"/>
    <SalC col7="A1" col8="1" col9="2" col10="False"/>
    <SalC col7="B" col8="1" col9="2" col10="False"/>
    <SalC col7="C" col8="1" col9="2" col10="True"/>
    <SalC col7="D" col8="1" col9="2" col10="False"/>
    <SalC col7="E" col8="1" col9="2" col10="False"/>
    <SalC col7="E1" col8="1" col9="2" col10="True"/>
    <SalC col7="F" col8="1" col9="2" col10="False"/>
</Sal>
<Sal col1="a3" col2="C" col3="12/9/2012" col4="d" col5="8" col6="True">
    <SalC col7="A" col8="1" col9="2" col10="False"/>
    <SalC col7="B" col8="1" col9="2" col10="False"/>
    <SalC col7="C" col8="1" col9="2" col10="False"/>
    <SalC col7="D" col8="1" col9="2" col10="True"/>
    <SalC col7="E" col8="1" col9="2" col10="False"/>
</Sal>

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

使用XSLT可以轻松解决这个问题,而无需在工作流程中引入Python,但是,如果必须使用Python,lxml.etree可以方便地引入一个新的类lxml.etree.XSLT,您可以利用它来利用它。< / p>

假设您的XML数据位于名为 xmlfile.xml 的文件中,则以下代码应有效。

<强> xsltfile.xsl

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text" />
        <xsl:template match="SalC">
                <xsl:value-of select="concat(../@col1,',', ../@col2,',',../@col3,',',../@col4,',',../@col5,',',../@col6,',',@col7,',',@col8,',',@col9,',',@col10)" />
        </xsl:template>
</xsl:stylesheet>

示例代码

from lxml import etree

xsltfile = etree.XSLT(etree.parse('xsltfile.xsl'))
xmlfile = etree.parse('xmlfile.xml')
output = xsltfile(xmlfile)
print(output)

答案 1 :(得分:0)

sal.attrib就像dict一样:

row = dict(sal.attrib)

salc.attrib也像dict一样。为了“扁平化” - 或者更确切地说,加入 - 两个词组,你可以使用dict.update

row.update(salc.attrib)

假设每个SalC元素都有col7col8cal9col10属性,您只需为每个{{row.update(salc.attrib)调用salc 1 {} sal


import lxml.etree as ET
import csv

text = '''\
<root>
<Sal col1="a1" col2="C" col3="12/5/2012" col4="a" col5="8" col6="True">
    <SalC col7="A" col8="1" col9="2" col10="True"/>
...
    <SalC col7="D" col8="1" col9="2" col10="True"/>
    <SalC col7="E" col8="1" col9="2" col10="False"/>
</Sal>
</root>'''

fieldnames = ('col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col6', 'col7', 'col8', 
              'col9', 'col10')

with open('/tmp/output.csv', 'wb') as f:
    writer = csv.DictWriter(f, fieldnames, delimiter = ',', lineterminator = '\n', )
    writer.writeheader()
    root = ET.fromstring(text)
    for sal in root.xpath('//Sal'):
        row = dict(sal.attrib)
        for salc in sal:
            row.update(salc.attrib)
            writer.writerow(row)

产量

col1,col2,col3,col4,col5,col6,col6,col7,col8,col9,col10
a1,C,12/5/2012,a,8,True,True,A,1,2,True
a1,C,12/5/2012,a,8,True,True,A1,1,2,False
a1,C,12/5/2012,a,8,True,True,B,1,2,False
...
a3,C,12/9/2012,d,8,True,True,B,1,2,False
a3,C,12/9/2012,d,8,True,True,C,1,2,False
a3,C,12/9/2012,d,8,True,True,D,1,2,True
a3,C,12/9/2012,d,8,True,True,E,1,2,False