使用XSLT 2.0进行两阶段转换

时间:2011-04-24 18:46:05

标签: xslt xslt-2.0

我正在尝试将CS​​V文件作为输入并将其转换为XML。我是XSLT的新手,我找到了一种将CSV转换为XML的方法(使用Andrew Welch中的示例),如下所示:

输入CSV文件:

car manufacturer,model,color,price,inventory
subaru,outback,blue,23195,54
subaru,forester,silver,20495,23

我的输出XML将是:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">outback</column>
      <column name="color">blue</column>
      <column name="price">23195</column>
      <column name="inventory">54</column>
   </row>
   <row>
      <column name="car manufacturer">subaru</column>
      <column name="model">forester</column>
      <column name="color">silver</column>
      <column name="price">20495</column>
      <column name="inventory">23</column>
   </row>
</rows>

我想要的输出实际上类似于:

<stock>
   <model>
      <car>subaru outback</car>
      <color>blue</color>
      <price>23195</price>
      <inventory>54</inventory>
   </model>
   <model>
      <car>subaru forester</car>
      <color>silver</color>
      <price>20495</price>
      <inventory>23</inventory>
   </model>
</stock>

我读到的是最好使用两相变换来完成。 CSV到XML是使用XSLT 2.0完成的,所以我认为在不使用节点集函数的情况下也可以使用它完成两个阶段转换。

所以第一阶段是将原始CSV文件作为输入,然后输出上面显示的中间XML。然后获取该中间XML,并将其传递给另一个转换以获得所需的输出。

任何人都可以帮助解决两阶段转型的问题吗?我将第一阶段的输出作为阶段2的输入传递出来了吗?

到目前为止我有这样的事情:

<xsl:import href="csv2xml.xsl"/>
<xsl:output method="xml" indent="yes" />

<xsl:variable name="intermediate">
    <xsl:apply-templates select="/" mode="csv2xml"/>
</xsl:variable>

<xsl:template match="rows" name="main">

 **[This is what I'm having trouble with]**

</xsl:template>

3 个答案:

答案 0 :(得分:7)

我没有看到为什么这种转换需要两个阶段的任何原因 - 除了允许您重用其中一个阶段的现有代码。

但是,当您确实需要两个阶段时,一般模型是:

<xsl:template match="/">
  <xsl:variable name="phase-1-result">
    <xsl:apply-templates select="/" mode="phase-1"/>
  </xsl:variable>
  <xsl:apply-templates select="$phase-1-result" mode="phase-2"/>
</xsl:template>

第1阶段和第2阶段的模板规则(及其应用模板调用)分别处于模式阶段1或阶段2。

答案 1 :(得分:2)

这个XSLT 2.0样式表:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="vLines"
         select="tokenize(unparsed-text('test.txt'),'(&#xD;)?&#xA;')"/>
        <xsl:variable name="vHeaders"
         select="tokenize($vLines[1],',')"/>
        <stock>
            <xsl:for-each select="$vLines[position()!=1]">
                <model>
                    <xsl:variable name="vColumns" select="tokenize(.,',')"/>
                    <xsl:for-each select="$vColumns">
                        <xsl:variable name="vPosition" select="position()"/>
                        <xsl:variable name="vHeader"
                         select="$vHeaders[$vPosition]"/>
                        <xsl:choose>
                            <xsl:when test="$vHeader = 'car manufacturer'">
                                <column name="car">
                                    <xsl:value-of
                                     select="(.,$vColumns[
                                                   index-of($vHeaders,'model')
                                                ])"/>
                                </column>
                            </xsl:when>
                            <xsl:when test="$vHeader = 'model'"/>
                            <xsl:otherwise>
                                <column name="{$vHeader}">
                                    <xsl:value-of select="."/>
                                </column>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
                </model>
            </xsl:for-each>
        </stock>
    </xsl:template>
</xsl:stylesheet>

输出:

<stock>
    <model>
        <column name="car">subaru outback</column>
        <column name="color">blue</column>
        <column name="price">23195</column>
        <column name="inventory">54</column>
    </model>
    <model>
        <column name="car">subaru forester</column>
        <column name="color">silver</column>
        <column name="price">20495</column>
        <column name="inventory">23</column>
    </model>
</stock>

注意:在XSLT 3.0中,您可以将模板应用于一般项目。

编辑:正确的名称。

答案 2 :(得分:2)

您可以在此处找到如何使用XSLT 3.0执行此操作的示例:

http://www.stylusstudio.com/tutorials/intro-xslt-3.html

在“文本操作”下查看。