使用XSL转换进行XML到CSV的转换

时间:2014-04-24 08:34:31

标签: xml xslt csv

我一直在使用Convert an XML file to CSV file using java方法处理xml到csv转换。但是我的.xsl文件无法产生预期的.csv结果。

我该怎么办?我该如何更改我的.xsl文件?

这是我的.xml文件

<RowOfValues>
<RowValue>
<Value>XYZ</Value>
</RowValue>
<RowValue>
<Value>xyz1</Value>
</RowValue>
<RowValue>
<Value>xyz2</Value>
</RowValue>
<RowValue>
<Value>xyz3</Value>
</RowValue>
<RowValue>
<Value>xyz4</Value>
</RowValue>
</RowOfValues>
<RowOfValues>
<RowValue>
<Value>ABC</Value>
</RowValue>
<RowValue>
<Value>abc1</Value>
</RowValue>
<RowValue>
<Value>abc2</Value>
</RowValue>
<RowValue>
<Value>abc3</Value>
</RowValue>
<RowValue>
<Value>abc4</Value>
</RowValue>
</RowOfValues>

这是我的.xsl文件

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
    <xsl:template match="/">
        RowValue,Value
            <xsl:for-each select="//RowOfValues">
                <xsl:for-each select="//RowValue">
                    <xsl:value-of select="concat(Value,',','&#xA;')"/>
                </xsl:for-each>
            </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

当前结果(csv):

RowValue,值

XYZ,
xyz1,
xyz2,
xyz3,
xyz4,
ABC,
abc1,
abc2,
abc3,
abc4,

预期结果(csv):

RowValue,Value
XYZ ABC
xyz1,abc1
xyz2,abc2
xyz3,abc3
xyz4,abc4

2 个答案:

答案 0 :(得分:0)

假设只有2列(即RowOfValues),并假设两列的长度相同:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                              xmlns:fo="http://www.w3.org/1999/XSL/Format" >
   <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
   <xsl:template match="/">
      <xsl:value-of select="concat('RowValue,Value', '&#xA;')"/>
      <xsl:for-each select="//RowOfValues[1]/RowValue">
         <xsl:variable name="pos" select="position()"/>
         <xsl:value-of select="concat(normalize-space(
                       concat(., ',', //RowOfValues[2]/RowValue[position()=$pos])),
                    '&#xA;')"/>
      </xsl:for-each>
   </xsl:template>
</xsl:stylesheet>

修改

这是使用调用模板接近N列案例的一种方法,尽管相当必要:(

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
         xmlns:fo="http://www.w3.org/1999/XSL/Format" >
   <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
   <xsl:template match="/">
      <xsl:value-of select="concat('RowValue,Value', '&#xA;')"/>
      <xsl:for-each select="//RowOfValues[1]/RowValue">
         <xsl:variable name="pos" select="position()"/>
         <xsl:value-of select="normalize-space(.)"/>
         <xsl:call-template name="ScrapeColumns">
            <xsl:with-param name="pos" select="$pos"/>
         </xsl:call-template>
         <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
   </xsl:template>

   <xsl:template name="ScrapeColumns">
      <xsl:param name="pos"></xsl:param>
      <xsl:for-each select="//RowOfValues[position() > 1]//RowValue[position()=$pos]">
         <xsl:value-of select="concat(', ', normalize-space(.))"/>
      </xsl:for-each>   
   </xsl:template>
</xsl:stylesheet>

毫无疑问,更优雅的解决方案。

答案 1 :(得分:0)

  

如果有超过2列,它如何实现

以这种方式尝试:

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

<xsl:key name="value-by-column" match="Value" use="count(../preceding-sibling::RowValue)" />

<xsl:template match="/">
    <xsl:for-each select="root/RowOfValues[1]/RowValue">
        <xsl:for-each select="key('value-by-column', count(preceding-sibling::RowValue))">
            <xsl:value-of select="."/>
            <xsl:if test="position()!=last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:if test="position()!=last()">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

这将容纳您可能拥有的任意数量的列。注意,假设每个&#34;列中的值的数量为&#34; (即RowOfValues)是平等的。

当应用于以下测试文档时:

<root>
   <RowOfValues>
      <RowValue>
         <Value>Col A</Value>
      </RowValue>
      <RowValue>
         <Value>a 1</Value>
      </RowValue>
      <RowValue>
         <Value>a 2</Value>
      </RowValue>
   </RowOfValues>
   <RowOfValues>
      <RowValue>
         <Value>Col B</Value>
      </RowValue>
      <RowValue>
         <Value>b 1</Value>
      </RowValue>
      <RowValue>
         <Value>b 2</Value>
      </RowValue>
   </RowOfValues>
   <RowOfValues>
      <RowValue>
         <Value>Col C</Value>
      </RowValue>
      <RowValue>
         <Value>c 1</Value>
      </RowValue>
      <RowValue>
         <Value>c 2</Value>
      </RowValue>
   </RowOfValues>
</root>

结果是:

Col A,Col B,Col C
a 1,b 1,c 1
a 2,b 2,c 2