XSLT-嵌套XML到CSV输出

时间:2018-07-23 08:39:37

标签: xml csv xslt

我正在尝试使用XSLT将XML文件转换为CSV。我有以下要转换的XML文件(手动简化版)。每个XML文件可以包含N条记录,其中N条可以变化。

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<reportheader>
<name>REPORT 1</name>
<version>v1</version>
</reportheader>
<recordtype>
    <account>
    <accountname>B</accountname>
    </account>
    <record>
    <time>12:00:00</time>
    <qty>10</qty>
    <price>20</price>
    </record>
    <record>
    <time>16:00:00</time>
    <qty>20</qty>
    <price>10</price>
    </record>   
</recordtype>
<recordtype>
    <account>
    <accountname>A</accountname>
    </account>
    <record>
    <time>16:00:00</time>
    <qty>5</qty>
    <price>10</price>
    </record>   
</recordtype>
</report>

所需的输出如下:

name|version|accountname|time|qty|price
REPORT 1|v1|B|12:00:00|10|20
REPORT 1|v1|B|16:00:00|20|10
REPORT 1|v1|A|16:00:00|5|10

我当前的方法是拥有两个脚本。一个XSLT,输出所有根节点和直接父节点。然后,在第二个XSLT中,我计算记录节点的数量,并循环N次遍历csv列名称。然后,我寻找匹配/ record / time [N]的例子。当前方法大量借鉴了https://pragmaticintegrator.wordpress.com/2012/10/28/transforming-xml-to-csv-via-xslt/

我目前的方法有两个问题。在图1中,假设每个记录始终具有每个可用字段。 2.我无法为记录分配正确的帐户,因为100条记录可能只有6个帐户。它们在xml文件中“松散耦合”的方式使我的方法无效。

有人可以帮助我找到一种更强大有效的方法吗?预先感谢。

2 个答案:

答案 0 :(得分:1)

通过使用ancestor轴查找表亲值,您可以一次性完成操作

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/">
    <xsl:text>name|version|accountname|time|qty|price&#xd;&#xa;</xsl:text>
    <xsl:apply-templates select="//record"/>
  </xsl:template>
  <xsl:template match="record">
    <xsl:value-of select="ancestor::report/reportheader/name"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="ancestor::report/reportheader/version"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="ancestor::recordtype/account/accountname"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="time"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="qty"/>
    <xsl:text>|</xsl:text>
    <xsl:value-of select="price"/>
    <xsl:text>&#xd;&#xa;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

 <xsl:output method="text"/>
    <xsl:template match="report">
        <xsl:for-each select="reportheader">
            <xsl:value-of select="name/local-name(),version/local-name(), following-sibling::recordtype[1]/account/accountname/local-name(),following-sibling::recordtype[1]/record[1]/time/local-name(),following-sibling::recordtype[1]/record[1]/qty/local-name(),following-sibling::recordtype[1]/record[1]/price/local-name()" separator="|"/>
            </xsl:for-each>
        <xsl:for-each select="recordtype/record">
            <xsl:text>&#x0a;</xsl:text>
            <xsl:value-of select=" ancestor::report/reportheader/name,ancestor::report/reportheader/version, preceding-sibling::account/accountname,time,qty,price" separator="|"/>

        </xsl:for-each>
    </xsl:template>
You may also try it.