XSLT:从xml生成csv,它有多个标签出现的复杂场景

时间:2012-07-11 07:13:49

标签: xml xslt

对于这个xml:

 <G>
        <P>
            <A>
                <b>value b</b>
                <c>value c</c>
            </A>
            <A>
                <b>value b2</b>
                <c>value c2</c>
            </A>
            <D>value ew</D>
        <D>value e2</D>     
            <E>value f</E>
        </P>
        <P>
            <A>
                <b>value bx</b>
                <c>value cx</c>
            </A>
            <A>
                <b>value b2x</b>
                <c>value c2x</c>
            </A>
             <D>value exw</D>
        <D>value ex2</D>

         <D>value ex2</D>
            <E>value fx</E>
        </P>
    </G>

像A和D这样的标签可以多次出现,我工作的原始xml有很多标签,其中很多都有多个出现。 我必须将输出作为:zh 值b值c值ew值f
值b值c值e2值f
值b2值c2值ew值f
值b2值c2值e2值f
值bx值cx值exw值fx
值bx值cx值ex2值fx
值bx值cx值ex3值fx
值b2x值c2x值exw值fx
值b2x值c2x值ex2值fx
值b2x值c2x值ex3值fx

如果A标签有多个出现,这个xslt会生成正确的输出,但是当xml上面的其他标签像D这样重复时,这不起作用。

<xsl:for-each select="//A">
    <xsl:value-of select="b"/>
    <xsl:text>,</xsl:text>
    <xsl:value-of select="c"/>
    <xsl:text>,</xsl:text>
    <xsl:value-of select="ancestor::P/D"/>
    <xsl:text>,</xsl:text>
    <xsl:value-of select="ancestor::P/E"/>
    <xsl:text>  
</xsl:text>
</xsl:for-each>

请建议正确的xslt

2 个答案:

答案 0 :(得分:1)

这是一个可能的解决方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:variable name='s' select='","' />
    <xsl:template match="A">
        <xsl:variable name='b' select='b' />
        <xsl:variable name='c' select='c' />
        <xsl:for-each select="../D"><xsl:value-of select='$b' /><xsl:value-of select='$s' /><xsl:value-of select='$c' /><xsl:value-of select='$s' /><xsl:value-of select='.'/><xsl:value-of select='$s' /><xsl:value-of select='../E'/><xsl:text>
</xsl:text></xsl:for-each>
    </xsl:template>
    <xsl:template match="text()" />
</xsl:stylesheet>

请注意,它会查找所有A,并为每个A输出A的每个D兄弟的一行。 请注意,这是您想要的

它给出了输出:

value b,value c,value ew,value f
value b,value c,value e2,value f
value b2,value c2,value ew,value f
value b2,value c2,value e2,value f
value bx,value cx,value exw,value fx
value bx,value cx,value ex2,value fx
value bx,value cx,value ex2,value fx
value b2x,value c2x,value exw,value fx
value b2x,value c2x,value ex2,value fx
value b2x,value c2x,value ex2,value fx

答案 1 :(得分:1)

我认为这可以通过重复调用模板来实现。首先,您有一个匹配 A 的模板,但不是输出 b c 元素,而是将它们作为参数传递给与之匹配的模板 D elemenet

<xsl:template match="A">
  <xsl:apply-templates select="following-sibling::D">
     <xsl:with-param name="prefix">
        <xsl:value-of select="b"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="c"/>
     </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>

然后,在匹配 D 元素的模板中,您将前缀与D值连接,并将其传递给与 E 匹配的模板元件。

<xsl:template match="D">
  <xsl:param name="prefix"/>
  <xsl:apply-templates select="following-sibling::E">
     <xsl:with-param name="prefix">
        <xsl:value-of select="$prefix"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="."/>
     </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>

然后匹配 E 元素的模板可以输出整个字符串。这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text" indent="yes"/>

   <xsl:template match="/">
      <xsl:apply-templates select="//A"/>
   </xsl:template>

   <xsl:template match="A">
      <xsl:apply-templates select="following-sibling::D">
         <xsl:with-param name="prefix">
            <xsl:value-of select="b"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="c"/>
         </xsl:with-param>
      </xsl:apply-templates>
   </xsl:template>

   <xsl:template match="D">
      <xsl:param name="prefix"/>
      <xsl:apply-templates select="following-sibling::E">
         <xsl:with-param name="prefix">
            <xsl:value-of select="$prefix"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="."/>
         </xsl:with-param>
      </xsl:apply-templates>
   </xsl:template>

   <xsl:template match="E">
      <xsl:param name="prefix"/>
      <xsl:value-of select="$prefix"/>
      <xsl:text>,</xsl:text>
      <xsl:value-of select="."/>
      <xsl:value-of select="'&#13;'"/>
   </xsl:template>
</xsl:stylesheet>

应用于XML示例时,输出以下内容

value b,value c,value ew,value f
value b,value c,value e2,value f
value b2,value c2,value ew,value f
value b2,value c2,value e2,value f
value bx,value cx,value exw,value fx
value bx,value cx,value ex2,value fx
value bx,value cx,value ex2,value fx
value b2x,value c2x,value exw,value fx
value b2x,value c2x,value ex2,value fx
value b2x,value c2x,value ex2,value fx