使用键/值对的XSLT到CSV

时间:2016-09-15 15:09:06

标签: xml csv xslt xslt-1.0

我有一些XML输出,我想将其转换为CSV,但是对于包含键/值对的数据,它已被证明是最困难的。我已经尝试了很多次迭代,我终于需要一些帮助了。这是需要使用XSLT 1.0转换的XML。

<?xml version="1.0" encoding="UTF-8"?>
<status>
    <snapshot>
        <metrics>
            <entry>
                <key>time</key>
                <value>1001</value>
            </entry>
            <entry>
                <key>bytes</key>
                <value>104</value>
            </entry>
            <entry>
                <key>input</key>
                <value>13321</value>
            </entry>
            <entry>
                <key>output</key>
                <value>11002</value>
            </entry>
        </metrics>
        <timestamp>2016-01-12T01:00</timestamp>
        <metrics>
            <entry>
                <key>time</key>
                <value>1002</value>
            </entry>
            <entry>
                <key>bytes</key>
                <value>105</value>
            </entry>
            <entry>
                <key>input</key>
                <value>13322</value>
            </entry>
            <entry>
                <key>output</key>
                <value>11003</value>
            </entry>
        </metrics>
        <timestamp>2016-01-12T02:00</timestamp>
    </snapshot>
</status>

我希望输出看起来像这样:

time,bytes,input,output,timestamp
1001,104,13321,11002,2016-01-12T01:00
1002,105,13322,11003,2016-01-12T02:00

===添加我正在使用的XSLT ===

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:variable name="delimiter" select="','"/>

    <xsl:key name="field" match="entry/*" use="name()"/>

    <xsl:template match="/">

        <xsl:for-each select="/*/*/*/*/*[generate-id()=generate-id(key('field', name())[1])]">
            <xsl:value-of select="name()"/>

            <xsl:if test="position() != last()">
                <xsl:value-of select="$delimiter"/>
            </xsl:if>
         </xsl:for-each>

        <xsl:text>&#xa;</xsl:text>

        <xsl:for-each select="/*/sObject">

            <xsl:variable name="property" select="." />
            <xsl:for-each select="$property/*">

                <xsl:variable name="value" select="." />
                <xsl:value-of select="$value"/>
                <xsl:if test="position() != last()">
                    <xsl:value-of select="$delimiter"/>
                </xsl:if>
                <xsl:if test="position() = last()">
                    <xsl:text>&#xa;</xsl:text>
                </xsl:if>

             </xsl:for-each>

        </xsl:for-each>


     </xsl:template>
 </xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

根据您给出的示例xml和信息,请尝试以下 XSLT 1.0 这是一个带有动态方法的改进的简化版本。如果您的XML略有变化,您不必更改样式表(例如,添加entries):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">

    <xsl:output method="text"/>
    <xsl:strip-space elements="status snapshot"/>

    <xsl:template match="snapshot">

        <!-- generate the headline -->
        <xsl:apply-templates select="metrics[1]/entry/key | timestamp[1]" mode="heading"/>
        <xsl:text>&#10;</xsl:text>

       <!-- generate the content -->
        <xsl:for-each select="metrics">
            <xsl:for-each select="entry/value">
                <xsl:value-of select="concat(., ',')"/>
            </xsl:for-each>
            <xsl:value-of select="following-sibling::*[name() = 'timestamp'][1]"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>

    </xsl:template>

    <xsl:template match="metrics/entry/key" mode="heading">
        <xsl:value-of select="concat(., ',')"/>
    </xsl:template>

    <xsl:template match="timestamp" mode="heading">
        <xsl:value-of select="name()"/>
    </xsl:template>

</xsl:stylesheet>

<强>结果:

time,bytes,input,output,timestamp
1001,104,13321,11002,2016-01-12T01:00
1002,105,13322,11003,2016-01-12T02:00

<强>要求:

所有entry及其子项始终存在且相同。

答案 1 :(得分:0)

这也适用于XSLT 1.0

定义四个必需列。然后只选择匹配的键/值对。这样,输出中将考虑缺少键/值对,并忽略任何其他对。分隔符和列名称可以作为参数传递。

缺点:更改密钥名称时没有灵活性。

delims=

相关问题