2013-11-03 103 views
0

我試圖使用XSLT將XML(由源生成)轉換爲CSV。使用XSLT將複雜而簡單的XML轉換爲CSV

以下是由外部源生成的輸入XML。我不確定這是否是一個有效的XML,因爲Details標記的值是一個大列表。

<Data> 
<Details COLUMNS="Counterparty,Iteration,StartDateTime,Quantity"> 
ABC,1,23/10/2013 06:00,10 
ABC,1,23/10/2013 06:30,12 
ABC,1,23/10/2013 07:00,15 
ABC,1,23/10/2013 07:30,5 
ABC,1,23/10/2013 08:00,180 
ABC,1,23/10/2013 08:30,87 
ABC,1,23/10/2013 09:00,88 
ABC,1,23/10/2013 09:30,56 
ABC,1,23/10/2013 10:00,13 
ABC,1,24/10/2013 00:00,0 
ABC,1,24/10/2013 00:30,8.7 
ABC,1,24/10/2013 01:00,100.9 
ABC,1,24/10/2013 01:30,1.1 
ABC,1,24/10/2013 02:00,2.2 
ABC,1,24/10/2013 02:30,3.2 
ABC,1,24/10/2013 03:00,20 
ABC,1,24/10/2013 03:30,30 
</Details> 
</Data> 

我想創建一個XSLT,可以將此XML轉換爲CSV,如下所示。我在網上查看了許多鏈接,但無法創建這樣的XSL轉換。請幫忙!

Counterparty,StartDate,StartTime,EndTime,Volume 
ABC,23/10/2013,0600,0630,10 
ABC,23/10/2013,0630,0700,12 
ABC,23/10/2013,0700,0730,15 
ABC,23/10/2013,0730,0800,5 
ABC,23/10/2013,0800,0830,180 
. 
. 
. 
. 
ABC,24/10/2013,0300,0330,20 
ABC,24/10/2013,0330,0400,30 

添加基於註釋的詳細信息:我需要去的元素文本中,並對其進行操作(添加/修改/刪除文本)。如果能夠在沒有太多麻煩的情況下操作文本,我願意使用XSLT 2.0。每行文本之間有一個LF和CR。請讓我知道最好的方法。謝謝!

問候, 阿米特

+1

好吧,基本上'Details'元素已經*是一個CSV文件,所以你所有的XSLT需要做的就是輸出標題,然後輸出這個元素的內容吧? – IMSoP

+0

是的,就像現在這樣,一個空轉換將會爲你提供除標題外的所有內容(因爲默認模板將選擇元素文本)。 – harpo

+0

或者您是否試圖讓XSLT檢查CSV中的數據,以便您可以操縱日期列以在輸出中獲取比輸入更多的列,如示例中所示?如果是這樣,我不確定XSLT是否是正確的工具,因爲這不是一個XML結構。爲什麼不使用更通用的腳本語言,比如Perl,Awk,PHP等? – IMSoP

回答

1

下面的XSLT 2.0產生所需的輸出

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes" /> 

    <xsl:template match="/Data"> 
    <xsl:text>Counterparty,StartDate,StartTime,EndTime,Volume&#10;</xsl:text> 

    <xsl:for-each select="tokenize(Details/text(), '[&#10;&#13;]')"> 

     <xsl:analyze-string select="." regex="\s*([^,]+,[^,]+,[^,]+) +([0-9]+):([0-9]+),([0-9\.]+)"> 

     <xsl:matching-substring> 
      <xsl:variable name="prefix" select="regex-group(1)"/> 
      <xsl:variable name="hours" select="regex-group(2)"/> 
      <xsl:variable name="minutes" select="regex-group(3)"/> 
      <xsl:variable name="suffix" select="regex-group(4)"/> 

      <xsl:variable name="startTime" select="number($hours) * 60 + number($minutes)"/> 
      <xsl:variable name="endTime" select="$startTime + 30"/> 
      <xsl:variable name="endHours" select="format-number($endTime div 60, '00')"/> 
      <xsl:variable name="endMinutes" select="format-number($endTime mod 60, '00')"/> 

      <xsl:value-of select="concat($prefix, ',', $hours, $minutes, ',', $endHours, $endMinutes, ',', $suffix)"/><xsl:text>&#10;</xsl:text>   
     </xsl:matching-substring> 

     </xsl:analyze-string> 
    </xsl:for-each> 

    </xsl:template> 

</xsl:stylesheet> 

注:

  • 的XSLT使有關輸入文件的列的內容的一些假設和他們的分離器。如果問題中提供的示例不能很好地表示生產數據,則可能必須更改regex表達式。
  • 轉換應該適用於所有具有行分隔符換行符和/或換行符或其任意組合的輸入文件。雖然我沒有嘗試過。
  • XSLT對如何導出結束時間做了一些假設(+30分鐘)。這可能不得不改變。