1

以下代码将 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,
4

3 回答 3

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,
于 2012-09-12T12:52:52.243 回答
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>

templatefor/并添加逗号:

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

templatefor *inrow模式下。

于 2012-09-12T12:46:37.607 回答
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,
于 2012-09-12T12:53:27.413 回答