使用xslt将xml转换为csv

时间:2012-09-12 12:44:21

标签: xml xslt xpath

以下代码将xml更改为csv。

当它应用于下面的样本数据时,

 <Addy>
<Row>
<L>1</L>
<LD>Dwelling</LD>
<Th>Passage</Th>
</Row>
</ADDY>

它以这种格式生成一个csv文件,包括列名

 L,LD,Th
 1,Dwelling,Passage

想法是取消列名并在最后一个值的末尾添加逗号(,) 这样预期的结果是

1,Dwelling,passage,

3 个答案:

答案 0 :(得分:1)

删除

<xsl:for-each select="*/*/*[generate-id() = generate-id(key('field',name())[1])]">
    <xsl:value-of select="name()" />
    <xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
<xsl:text>&#10;</xsl:text>
来自template /

并添加逗号:

<xsl:text>,&#10;</xsl:text>
<{1}} template * row模式。

答案 1 :(得分:1)

如果每个Row的元素顺序相同,那么您不需要任何复杂的Muenchian分组,模板模式等。只需一个非常简单的样式表即可:

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

  <xsl:template match="Row">
    <xsl:apply-templates select="*" />
    <xsl:text>&#10;</xsl:text>
  </xsl:template>

  <xsl:template match="Row/*">
    <xsl:value-of select="." />
    <xsl:text>,</xsl:text>
  </xsl:template>
</xsl:stylesheet>

在以下输入上运行:

<Addy>
  <Row>
    <L>1</L>
    <LD>Dwelling</LD>
    <Th>Passage</Th>
  </Row>
  <Row>
    <L>2</L>
    <LD>Foo</LD>
    <Th>Bar</Th>
  </Row>
</Addy>

生成您所追求的输出,包括最后一列值之后的尾随逗号:

1,Dwelling,Passage,
2,Foo,Bar,

答案 2 :(得分:0)

只需修改与/匹配的模板,现在应该是:

   <xsl:template match="/">
    <xsl:apply-templates select="*/*" mode="row"/>
   </xsl:template>

如果你真的想在每行产生的末尾有一个尾随逗号,那么替换第一个出现的:

<xsl:if test="position() != last()">,</xsl:if>

使用:

<xsl:text>&#10;</xsl:text>

当仅执行这些最小修改时,提供的代码变为:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

   <xsl:key name="field" match="/*/*/*" use="name()" />
   <xsl:output method="text"/>

   <xsl:template match="/">
    <xsl:apply-templates select="*/*" mode="row"/>
   </xsl:template>

    <xsl:template match="*" mode="row">
    <xsl:variable name="row" select="*" />
    <xsl:for-each select="/*/*/*[generate-id() = generate-id(key('field',name())[1])]">
        <xsl:variable name="name" select="name()" />
        <xsl:apply-templates select="$row[name()=$name]" mode="data" />
        <xsl:text>,</xsl:text>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
    </xsl:template>

    <xsl:template match="*" mode="data">
    <xsl:choose>
        <xsl:when test="contains(text(),',')">
            <xsl:text>&quot;</xsl:text>
            <xsl:call-template name="doublequotes">
                <xsl:with-param name="text" select="text()" />
            </xsl:call-template>
            <xsl:text>&quot;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="." />
        </xsl:otherwise>
    </xsl:choose>
    <xsl:if test="position() != last()">,</xsl:if>
    </xsl:template>

    <xsl:template name="doublequotes">
    <xsl:param name="text" />
    <xsl:choose>
        <xsl:when test="contains($text,'&quot;')">
            <xsl:value-of select="concat(substring-before($text,'&quot;'),'&quot;&quot;')" />
            <xsl:call-template name="doublequotes">
                <xsl:with-param name="text" select="substring-after($text,'&quot;')" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text" />
        </xsl:otherwise>
    </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

对以下XML文档应用此转换时(请注意两个Row元素中子项的不同顺序)

<Addy>
  <Row>
    <L>1</L>
    <LD>Dwelling</LD>
    <Th>Passage</Th>
  </Row>
  <Row>
    <Th>Bar</Th>
    <LD>Foo</LD>
    <L>2</L>
  </Row>
</Addy>

产生了想要的正确结果

1,Dwelling,Passage,
2,Foo,Bar,