2012-05-01 210 views
0

我有一个样品XSLT计数兄弟

<Root> 
    <A rename="yes,it is option 1"/> 
    <C rename="no"/> 
    <A rename="yes,it is option 2"/> 
    <C rename="no"/> 
    <C rename="yes"/> 
    <C rename="no"/> 
    <A rename="yes,it is option 3"/> 
    <A rename="yes,it is option 4"/> 
    <C rename="no"/> 
    <C rename="yes"/> 
    <C rename="no"/>  
    <C rename="no"/>   
</Root> 

然后我将模板应用于这个样子

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:template match="A"> 
      <p><b>option1: <xsl:value-of select="count(following-sibling::C[preceding-sibling::A[1]/@rename[contains(.,'option 1')]])"/></b></p> 
      <p><b>option2: <xsl:value-of select="count(following-sibling::C[preceding-sibling::A[1]/@rename[contains(.,'option 2')]])"/></b></p>    
      <p><b>option3: <xsl:value-of select="count(following-sibling::C[preceding-sibling::A[1]/@rename[contains(.,'option 3')]])"/></b></p> 
      <p><b>option4: <xsl:value-of select="count(following-sibling::C[preceding-sibling::A[1]/@rename[contains(.,'option 4')]])"/></b></p>       
</xsl:template> 
</xsl:stylesheet> 

,但我想输出这个样子的,如果没有下面的兄弟姐妹,我们只是忽略这个one.just打印这些@rename包含“选项”,也包含元素

option1: 1 

option2: 3 

option4: 4 

我所得到的是现在

option1: 1 

option2: 3 

option3: 0 

option4: 4 

option1: 0 

option2: 3 

option3: 0 

option4: 4 

option1: 0 

option2: 0 

option3: 0 

option4: 4 

option1: 0 

option2: 0 

option3: 0 

option4: 4 
+1

现在,这是一个很好的例子,不使用XML。为什么在你不给数据任何结构时使用结构化格式? – Tomalak

+0

另外*您没有真正尝试*您输入的显示XSLT代码。我几乎得到你想要的输出。请在您的问题中多加一些注意,如果您的代码和问题文本讲述了两个不同的故事,则无法帮助您。 – Tomalak

+0

我只是想简化我的原始文件 –

回答

1

你指望所有跟随最近一个元素Ç元素。这可以通过一个键来完成,到组中的所有这样的Ç元件与相关联的元件

<xsl:key name="lookup" match="C" use="generate-id(preceding-sibling::A[1])" /> 

为了找到元素为其以下Ç存在至少一个,那么你这样做:

<xsl:apply-templates select="A[key('lookup', generate-id())]" /> 

然后再以数的期权数量,你可以算的元素数量的关键,像这样:

<xsl:value-of select="count(key('lookup', generate-id()))" /> 

当这个应用到你的XML样本尝试以下XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="yes"/> 
    <xsl:key name="lookup" match="C" use="generate-id(preceding-sibling::A[1])" /> 

    <xsl:template match="/Root"> 
     <xsl:apply-templates select="A[key('lookup', generate-id())]" /> 
    </xsl:template> 

    <xsl:template match="A"> 
     <xsl:value-of select="concat(@rename, ': ', count(key('lookup', generate-id())) , '&#13;&#13;')" /> 
    </xsl:template> 
</xsl:stylesheet> 

,下面是输出:

yes,it is option 1: 1 

yes,it is option 2: 3 

yes,it is option 4: 4 

请注意,如果你想 '选项1',而不是'是的,这是选项1',你可以做concat('option', substring-after(@rename, 'option '))而不是只是@rename

注意,这个问题可以简化d,如果你重新构建你的XML。这样的事情会好得多:

<Root> 
    <A rename="yes,it is option 1"> 
     <C rename="no"/> 
    </A> 
    <A rename="yes,it is option 2"> 
     <C rename="no"/> 
     <C rename="yes"/> 
     <C rename="no"/> 
    </A> 
    <A rename="yes,it is option 3"/> 
    <A rename="yes,it is option 4"> 
     <C rename="no"/> 
     <C rename="yes"/> 
     <C rename="no"/> 
     <C rename="no"/> 
    </A> 
</Root> 
+0

但A和C元素不是父母和孩子,他们只是兄弟姐妹, –

+0

是的,我知道!我只是说如果他们是父母和孩子,编码XSLT将会很容易。 –

+0

是的,我更加困惑于处理这些兄弟关系 –

0

在XSLT 2.0这个变成一个简单的分组问题,使用xsl:for-each-group指令。

<xsl:template match="Root"> 
    <xsl:for-each-group group-starting-with="A" select="*"> 
    <xsl:if test="count(current-group()) != 1"> 
     <p>Option <xsl:value-of select="substring-after(current-group()[1]/@rename, 'option ')"/> = <xsl:value-of select="count(current-group())-1"/></p>  </xsl:if> 
    </xsl:for-each-group> 
</xsl:template> 
+0

它似乎很有趣,我在哪里可以找到更多这样的例子? –

+0

我从书中学到了关于XSLT 2.0的所有知识,这是Wrox出色的XSLT 2.0程序员参考。 – samjudson

+0

哦,非常感谢你,这是一个XSLT 2.0程序员参考,第3版 迈克尔·凯 ISBN:978-0-7645-6909-8 平装 960页2004年8月 查看最近的这个称号版 –