XSLT将自定义XML转换为CSV

XSLT将自定义XML转换为CSV,xml,csv,xslt,Xml,Csv,Xslt,我想通过使用“;”作为值分隔符将自定义XML转换为csv。以下是我的XML: <?xml version="1.0" encoding="utf-8"?> <root> <operators> <item> <lfbis>1234567</lfbis> <name>Stefan Maier</name> &

我想通过使用“;”作为值分隔符将自定义XML转换为csv。以下是我的XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <operators>
        <item>
            <lfbis>1234567</lfbis>
            <name>Stefan Maier</name>
            <company />
            <street>Testweg 7</street>
            <citycode>95131</citycode>
            <city>Hof</city>
            <controlbody>BIKO</controlbody>
            <productdata>
                <item>Rinder</item>
                <item>9</item>
            </productdata>
        </item>
        <item>
            <lfbis>5671234</lfbis>
            <name>Antom Mueller</name>
        <company>Berghof</company>
            <street>Testweg 8</street>
            <citycode>95111</citycode>
            <city>Bamberg</city>
            <controlbody>BIKO</controlbody>
            <productdata>
                <item>Rinder</item>
                <item>9</item>
            </productdata>
        </item>
    </operators>
</root> 
现在,我试图实现的是productdata元素的子元素也被视为csv结果中的值。因此,我需要在值Rinder9之间使用“;”而不是“”(空格),例如我的csv看起来像:

1234567;Stefan Maier;;Testweg 7;95131;Hof;BIKO;Rinder;9;
5671234;Antom Mueller;Berghof;Testweg 8;95111;Bamberg;BIKO;Rinder;9;

下面是Tomalak代码的改编

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

  <xsl:output method="text" encoding="utf-8" />

  <xsl:param name="delim" select="';'" />
  <xsl:param name="quote" select="'&quot;'" />
  <xsl:param name="break" select="'&#xA;'" />

  <xsl:template match="/">
    <xsl:apply-templates select="root/operators/item" />
  </xsl:template>

  <xsl:template match="root/operators/item">
    <xsl:apply-templates select=".//*[not(*)]"/>
    <xsl:value-of select="$break" />
  </xsl:template>

  <xsl:template match="*">
    <xsl:if test="position() > 1">
      <xsl:value-of select="$delim"/>
    </xsl:if>
    <xsl:value-of select="normalize-space()" />
  </xsl:template>

  <xsl:template match="text()" />

</xsl:stylesheet>


下面是Tomalak代码的改编

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

  <xsl:output method="text" encoding="utf-8" />

  <xsl:param name="delim" select="';'" />
  <xsl:param name="quote" select="'&quot;'" />
  <xsl:param name="break" select="'&#xA;'" />

  <xsl:template match="/">
    <xsl:apply-templates select="root/operators/item" />
  </xsl:template>

  <xsl:template match="root/operators/item">
    <xsl:apply-templates select=".//*[not(*)]"/>
    <xsl:value-of select="$break" />
  </xsl:template>

  <xsl:template match="*">
    <xsl:if test="position() > 1">
      <xsl:value-of select="$delim"/>
    </xsl:if>
    <xsl:value-of select="normalize-space()" />
  </xsl:template>

  <xsl:template match="text()" />

</xsl:stylesheet>


一个简单的方法就是改变

<xsl:template match="*">


它匹配没有子元素的元素。这样做的效果是,当apply templates命中productData元素时,没有匹配的模板规则,因此默认的规则生效,即将模板应用于子元素


但是,这需要改变处理分隔符的策略。在您的情况下,这相当简单,因为您希望在每个项目(包括最后一个项目)后面都有一个分号:所以只需在输出每个项目后无条件地添加分号,而不要在行的末尾添加另一个分号。

一个简单的方法是更改

<xsl:template match="*">


它匹配没有子元素的元素。这样做的效果是,当apply templates命中productData元素时,没有匹配的模板规则,因此默认的规则生效,即将模板应用于子元素


但是,这需要改变处理分隔符的策略。在您的情况下,这相当简单,因为您希望在每个项目(包括最后一项)后面都有一个分号:因此,只需在输出每个项目后无条件地添加分号,并且不要在行的末尾添加另一个分号。

如果您要使用其他人的代码,请至少信任他们,而不要说是您编写的。这里有XSLT代码。是的,很抱歉,我当然使用了stackoverflow线程来编写xlst样式表。我向那个帖子里的人道歉,尤其是向样式表的作者道歉,因为他没有在我的问题中提到他。在以后的帖子中,我会更加小心。如果你要使用别人的代码,请至少相信他们,而不是说是你写的。这里有XSLT代码。是的,很抱歉,我当然使用了stackoverflow线程来编写xlst样式表。我向那个帖子里的人道歉,尤其是向样式表的作者道歉,因为他没有在我的问题中提到他。在以后的帖子中我会更加小心。谢谢Martin,我使用了您对@Tomalak代码的改编,xml get已经按照我想要的方式进行了转换。我在匹配root/operators/item元素的模板中添加了
select=“concat($delim,$break)”
,以便在每一行的最后一个值后面加上分号。感谢Martin,我使用了您对@Tomalak代码的改编,并以我想要的方式转换了xml get。我在匹配root/operators/item元素的模板中添加了
select=“concat($delim,$break)”
,以便在每行的最后一个值后面加上分号。
<xsl:template match="*[not(*)]">