[英]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>
</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>
</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> </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> </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, ' ')"/>
<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], ' ')"/>
</xsl:for-each>
</xsl:template>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.