簡體   English   中英

帶有鍵/值對的 XSLT 到 CSV

[英]XSLT to CSV with a key / value pair

我有一些 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>

根據您給出的示例 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及其子entry始終存在且相同。

這也適用於 XSLT 1.0

定義四個必需的列。 然后只選擇匹配的鍵/值對。 這樣,輸出中將考慮不存在的鍵/值對,並忽略任何其他對。 分隔符和列名可以作為參數傳遞。

缺點:在更改鍵名的情況下沒有靈活性。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:param name="del" select="','"/>
<xsl:param name="col1" select="'time'"/>
<xsl:param name="col2" select="'bytes'"/>
<xsl:param name="col3" select="'input'"/>
<xsl:param name="col4" select="'output'"/>
<xsl:param name="col5" select="'timestamp'"/>
<xsl:template match="/status/snapshot">
    <xsl:value-of select="concat($col1, $del, $col2, $del, $col3, $del, $col4, $del, $col5, '&#10;')"/>
    <xsl:for-each select="metrics">
        <xsl:variable name="pos" select="position()"/>
        <xsl:value-of select="concat(entry[key = $col1]/value, $del)"/>
        <xsl:value-of select="concat(entry[key = $col2]/value, $del)"/>
        <xsl:value-of select="concat(entry[key = $col3]/value, $del)"/>
        <xsl:value-of select="concat(entry[key = $col4]/value, $del)"/>
        <xsl:value-of select="concat(../timestamp[$pos], '&#10;')"/>
    </xsl:for-each>
</xsl:template>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM