2011-01-31 45 views
1

我有以下xml,其中包含产品信息。每个产品的描述有时会在下一个产品之前的下一行中出现,因为在特定数量的字符之后,描述被分割。xsl中的递归调用问题与以下兄弟问题

<?xml version="1.0" encoding="utf-8"?> 
<root> 
<row> 
    <rowWords>5.00</rowWords> 
    <rowWords>PRODUCTCODE1</rowWords> 
    <rowWords>DESCRIPTIONWORD1</rowWords> 
    <rowWords>DESCRIPTIONWORD2</rowWords> 
    <rowWords>DESCRIPTIONWORD3</rowWords> 
    <rowWords>DESCRIPTIONWORD4</rowWords> 
    <rowWords>DESCRIPTIONWORD5</rowWords> 
    <rowWords>11.28</rowWords> 
    <rowWords>56.40</rowWords> 
</row> 
<row> 
    <rowWords>DESCRIPTIONWORD6</rowWords> 
</row> 
<row> 
    <rowWords>6.00</rowWords> 
    <rowWords>PRODUCTCODE2</rowWords> 
    <rowWords>DESCRIPTIONWORD1</rowWords> 
    <rowWords>DESCRIPTIONWORD2</rowWords> 
    <rowWords>DESCRIPTIONWORD3</rowWords> 
    <rowWords>DESCRIPTIONWORD4</rowWords> 
    <rowWords>DESCRIPTIONWORD5</rowWords> 
    <rowWords>11.00</rowWords> 
    <rowWords>66.00</rowWords> 
</row> 
<row> 
    <rowWords>DESCRIPTIONWORD6</rowWords> 
    <rowWords>DESCRIPTIONWORD7</rowWords> 
    <rowWords>DESCRIPTIONWORD8</rowWords> 
</row> 
<row> 
    <rowWords>DESCRIPTIONWORD9</rowWords> 
    <rowWords>DESCRIPTIONWORD10</rowWords> 
</row> 
<row> 
    <rowWords>10.00</rowWords> 
    <rowWords>PRODUCTCODE3</rowWords> 
    <rowWords>DESCRIPTIONWORD1</rowWords> 
    <rowWords>DESCRIPTIONWORD2</rowWords> 
    <rowWords>10.00</rowWords> 
    <rowWords>100.00</rowWords> 
</row> 
    . 
    . any amount of rows containing products 
    . 
</root> 

说明以及产品数量的变化,所以我不知道如何把产品的描述汇集在一条线上。

这是我已经完成的xsl。

<?xml version='1.0'?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="something"> 
<xsl:output indent="yes"/> 
<xsl:template match="/root"> 
<a:Invoice> 
    <Products> 
    <xsl:for-each select="row[position()&gt;=5 and position()&lt;=last()-5]"> 
    <!-- With this if, i prevent create a product node with partial description--> 
    <xsl:if test="number(rowWords[1])"> 
    <Product> 
     <xsl:attribute name="quantity"><xsl:value-of select="rowWords[1]"/></xsl:attribute> 
     <xsl:attribute name="productCode"><xsl:value-of select="rowWords[2]"/></xsl:attribute> 
     <!--Here is the problem (Thank you Dimitri) --> 
     <xsl:attribute name="description"> 
     <xsl:call-template name="constructDescription"> 
      <xsl:with-param name="pRow" select="."/> 
       <xsl:with-param name="pPosition" select="position()"/> 
      </xsl:call-template> 
     </xsl:attribute> 
     <xsl:attribute name="unitValue"><xsl:value-of select="rowWords[last()-1]"/></xsl:attribute> 
     <xsl:attribute name="amount"><xsl:value-of select="rowWords[last()]"/></xsl:attribute> 
    </Product> 
    </xsl:if> 
    </xsl:for-each> 
    </Products> 
</a:Invoice> 
</xsl:template> 


<xsl:template name="constructDescription"> 
    <xsl:param name="pRow"/> 
    <xsl:param name="pPosition"/> 
    <xsl:for-each select="$pRow/*[position() >= 3 and position() &lt;= last() -2]"> 
     <xsl:value-of select="concat(.,' ')"/> 
    </xsl:for-each> 
    <xsl:if test="$pRow/following-sibling::*[not(number(*[1])=number(*[1]))]"> 
     <xsl:call-template name="constructDescription"> 
      <xsl:with-param name="pRow" select="$pRow/following-sibling:: 
       *[position()=number($pPosition)+1]"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

这是输出

<?xml version='1.0' ?> 
<a:Invoice> 
    <Products> 
    <Product quantity="5.00" productCode="PRODUCTCODE1" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 " unitValue="11.28" amount="56.40"/> 
    <Product quantity="6.00" productCode="PRODUCTCODE2" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 " unitValue="11.00" amount="66.00"/> 
    <Product quantity="10.00" productCode="PRODUCTCODE3" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 " unitValue="10.00" amount="100.00"/> 
    </Products> 
</a:Invoice> 

发生了什么事?问题是当我再次调用constructDescription!但我不知道如何解决它!

非常感谢!

+0

您要求我们阅读大量的XML。是否需要解释这个问题? – 2011-01-31 04:25:07

+0

谢谢你,约翰!我改变了我问的方式!我希望它更清晰 – jechaviz 2011-01-31 08:42:56

回答

2

这种变换使用了命名模板,其中,当用参数,其容纳产品的row调用,产生一个字符串,与完整描述

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:key name="kFollowingDesc" 
match="row[not(number(*[1])=number(*[1]))]" 
use="generate-id(preceding-sibling::row[number(*[1])=number(*[1])][1])"/> 


<xsl:template match="/"> 
    <xsl:call-template name="constructDescription"> 
    <xsl:with-param name="pRow" select="/*/*[1]"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="constructDescription"> 
    <xsl:param name="pRow"/> 

    <xsl:for-each select= 
     "$pRow/*[position() >= 3 
      and 
       not(position() > count($pRow/*) -2) 
       ] 
"> 
    <xsl:value-of select="concat(.,' ')"/> 
</xsl:for-each> 
    <xsl:for-each select="key('kFollowingDesc', generate-id($pRow))"> 
     <xsl:value-of select="concat(.,' ')"/> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

当该变换被应用在下面的XML文档(你的,但良好和显著截断):

<root> 
    <row> 
     <rowWords>6.00</rowWords> 
     <rowWords>PRODUCTCODE2</rowWords> 
     <rowWords>DESCRIPTIONWORD1</rowWords> 
     <rowWords>DESCRIPTIONWORD2</rowWords> 
     <rowWords>DESCRIPTIONWORD3</rowWords> 
     <rowWords>DESCRIPTIONWORD4</rowWords> 
     <rowWords>DESCRIPTIONWORD5</rowWords> 
     <rowWords>DESCRIPTIONWORD6</rowWords> 
     <rowWords>DESCRIPTIONWORD7</rowWords> 
     <rowWords>DESCRIPTIONWORD8</rowWords> 
     <rowWords>DESCRIPTIONWORD9</rowWords> 
     <rowWords>11.00</rowWords> 
     <rowWords>66.00</rowWords> 
    </row> 
    <row> 
     <rowWords>DESCRIPTIONWORD10</rowWords> 
     <rowWords>DESCRIPTIONWORD11</rowWords> 
     <rowWords>DESCRIPTIONWORD12</rowWords> 
     <rowWords>DESCRIPTIONWORD13</rowWords> 
    </row> 
</root> 

中的想要的,正确的描述产生

DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 DESCRIPTIONWORD10 DESCRIPTIONWORD11 DESCRIPTIONWORD12 DESCRIPTIONWORD13 

说明:此命名模板应该是不言自明的,除了测试,如果一些项目是一个数字,它是:

number($x) = number($x) 

$x是一个数字(或可以成功转换为数字的任何类型的值)时,它的计算结果为true()

我们正在测试:

not(number(*[1])=number(*[1])) 

计算结果为true()只有当第一rowWords孩子下一行是不是一个数字 - 这意味着它包含更多的说明文字。

最后:所有这一切,融入了OP的代码:

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

    <xsl:key name="kFollowingDesc" 
    match="row[not(number(*[1])=number(*[1]))]" 
    use="generate-id(preceding-sibling::row[number(*[1])=number(*[1])][1])"/> 

    <xsl:template match="/root"> 
     <a:Invoice> 
      <Products> 
       <xsl:for-each select="row[number(*[1])=number(*[1])]"> 
        <!-- With this if, i prevent create a product node with partial description--> 
        <xsl:if test="number(rowWords[1])"> 
         <Product> 
          <xsl:attribute name="quantity"> 
           <xsl:value-of select="rowWords[1]"/> 
          </xsl:attribute> 
          <xsl:attribute name="productCode"> 
           <xsl:value-of select="rowWords[2]"/> 
          </xsl:attribute> 
          <!--Here is the problem (Thank you Dimitri) --> 

          <xsl:variable name="vDescriptions"> 
           <xsl:call-template name="constructDescription"> 
            <xsl:with-param name="pRow" select="."/> 
           </xsl:call-template> 
          </xsl:variable> 
          <xsl:attribute name="description"> 
           <xsl:value-of select="normalize-space($vDescriptions)"/> 
          </xsl:attribute> 
          <xsl:attribute name="unitValue"> 
           <xsl:value-of select="rowWords[last()-1]"/> 
          </xsl:attribute> 
          <xsl:attribute name="amount"> 
           <xsl:value-of select="rowWords[last()]"/> 
          </xsl:attribute> 
         </Product> 
        </xsl:if> 
       </xsl:for-each> 
      </Products> 
     </a:Invoice> 
    </xsl:template> 

    <xsl:template name="constructDescription"> 
     <xsl:param name="pRow"/> 

     <xsl:for-each select= 
      "$pRow/*[position() >= 3 
       and 
        not(position() > count($pRow/*) -2) 
        ] 
    "> 
     <xsl:value-of select="concat(.,' ')"/> 
    </xsl:for-each> 
     <xsl:for-each select="key('kFollowingDesc', generate-id($pRow))"> 
      <xsl:value-of select="concat(.,' ')"/> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

当这种转变是在他提供新的XML文档应用:

<root> 
    <row> 
     <rowWords>5.00</rowWords> 
     <rowWords>PRODUCTCODE1</rowWords> 
     <rowWords>DESCRIPTIONWORD1</rowWords> 
     <rowWords>DESCRIPTIONWORD2</rowWords> 
     <rowWords>DESCRIPTIONWORD3</rowWords> 
     <rowWords>DESCRIPTIONWORD4</rowWords> 
     <rowWords>DESCRIPTIONWORD5</rowWords> 
     <rowWords>11.28</rowWords> 
     <rowWords>56.40</rowWords> 
    </row> 
    <row> 
     <rowWords>DESCRIPTIONWORD6</rowWords> 
    </row> 
    <row> 
     <rowWords>6.00</rowWords> 
     <rowWords>PRODUCTCODE2</rowWords> 
     <rowWords>DESCRIPTIONWORD1</rowWords> 
     <rowWords>DESCRIPTIONWORD2</rowWords> 
     <rowWords>DESCRIPTIONWORD3</rowWords> 
     <rowWords>DESCRIPTIONWORD4</rowWords> 
     <rowWords>DESCRIPTIONWORD5</rowWords> 
     <rowWords>11.00</rowWords> 
     <rowWords>66.00</rowWords> 
    </row> 
    <row> 
     <rowWords>DESCRIPTIONWORD6</rowWords> 
     <rowWords>DESCRIPTIONWORD7</rowWords> 
     <rowWords>DESCRIPTIONWORD8</rowWords> 
    </row> 
    <row> 
     <rowWords>DESCRIPTIONWORD9</rowWords> 
     <rowWords>DESCRIPTIONWORD10</rowWords> 
    </row> 
    <row> 
     <rowWords>10.00</rowWords> 
     <rowWords>PRODUCTCODE3</rowWords> 
     <rowWords>DESCRIPTIONWORD1</rowWords> 
     <rowWords>DESCRIPTIONWORD2</rowWords> 
     <rowWords>10.00</rowWords> 
     <rowWords>100.00</rowWords> 
    </row> . . any amount of rows containing products . 
</root> 

通缉,正确结果产生

<a:Invoice xmlns:a="something"> 
<Products> 
<Product quantity="5.00" productCode="PRODUCTCODE1" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6" unitValue="11.28" amount="56.40" /> 
<Product quantity="6.00" productCode="PRODUCTCODE2" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2 DESCRIPTIONWORD3 DESCRIPTIONWORD4 DESCRIPTIONWORD5 DESCRIPTIONWORD6 DESCRIPTIONWORD7 DESCRIPTIONWORD8 DESCRIPTIONWORD9 DESCRIPTIONWORD10" unitValue="11.00" amount="66.00" /> 
<Product quantity="10.00" productCode="PRODUCTCODE3" description="DESCRIPTIONWORD1 DESCRIPTIONWORD2" unitValue="10.00" amount="100.00" /> 
</Products> 
</a:Invoice>