2016-03-19 32 views
0

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

<?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> 

我迄今管理(使用计算器线程 XML to CSV Using XSLT,尤其是使用代码在他的回答...a version with configurable parameters that you can set programmatically写道通过@Tomalak)使用以下XSLT转换:

<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="item"> 
    <xsl:apply-templates /> 
    <!--<xsl:if test="following-sibling::*">--> 
     <xsl:value-of select="concat($delim, $break)" /> 
    <!--</xsl:if>--> 
    </xsl:template> 

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

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

</xsl:stylesheet> 

...,我使用xsltproc的得到以下结果:

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

现在,我想实现的是, 项目产品数据元素的子元素也被视为csv结果中的值。所以我需要一个“;”而不是 “”(空格)的值Rinder和之间,比如我的CSV会是什么样子:

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

如果您要使用其他人的代码,请至少声明他们而不是说你写了它。您可以从http://stackoverflow.com/a/365372/18771获取XSLT代码。 – Tomalak

+0

是的,对不起,我当然使用了stackoverflow线程来编写xlst样式表。我向那个线程中的人们道歉,特别是对于样式表的作者,在我的问题中没有提及他。我将在未来的职位更加小心。 –

回答

1

这里是托默勒格的代码适应

<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> 

当你有两种类型item元素我需要一个相当明确的匹配模式。

+0

感谢Martin,我使用了@Tomalak的代码,并且xml get以我想要的方式改变了方向。我在匹配_root/operators/item_元素的模板中添加了'select =“concat($ delim,$ break)”',以便在每行的最后一个值之后加上一个分号。 –

2

一个简单的方法是改变

<xsl:template match="*"> 

<xsl:template match="*[not(*)]"> 
它匹配没有一个子元素元素

。其效果是,当apply-templates访问productData元素时,没有匹配的模板规则,因此默认启动,即将模板应用于子项。

但是这需要改变处理分隔符的策略。在你的情况下,这很容易,因为你需要在包含最后一个项目的每一项之后使用分号:所以在输出每个项目后无条件地添加分号,并且不要在该行的末尾添加另一个分号。

+0

谢谢迈克尔指引我在正确的方向! –