2012-11-11 25 views
1

我需要一个XSLT 1.0测试表达式,将指示当前结点t的元素是否是完全交错,这样XPath来检测儿童是否被交错

<t> 
    <cat /> 
    <dog /> 
    <horse /> 
    <cat /> 
    <dog /> 
    <horse /> 
</t> 

或有一些其它顺序,如

<t> 
    <cat /> 
    <cat /> 
    <dog /> 
    <dog /> 
    <horse /> 
    <horse /> 
</t> 

<t> 
    <cat /> 
    <dog /> 
    <cat/> 
    <horse/> 
    <cat/> 
    <horse /> 
</t> 

如果第一,可以有任意数量的这种元组。如果第二个,可以有任何数量(包括零)的每种孩子,并以任何顺序。

一只猫,一只狗,一匹马的特殊情况可以测试真或假,无论哪种算法都更容易。

我事先知道三个元素的名称。


编辑。在Dimitre的要求下,让我试着说另一种,也许更简单的方法。

上下文节点具有任意数量的子节点,但每个子节点只有三个名称中的一个。在处理这些孩子之前,我需要测试它们是否以重复模式出现,例如ABCABCABC或CABCAB,或者其他三个重复三元组​​的组合,其中每个三元组出现一次(ABCABC测试为真,ABBABB测试为假) 。

+0

是否“可以有任意数量的” 1个或多个元组所有的情况下返回真有点不违背“我知道了_three_元素的名称“? –

+0

只有三种元素,我知道他们的名字。但是(在非交错的情况下),可以有任何数量的每种实例。 – JPM

+0

元素是否总是以给定的顺序交错排列,或者顺序可能不同,他们只需要定期分发? – nine9ths

回答

0
test="name(*[last()])=name(*[3]) 
    and name(*[1])!=name(*[2]) 
    and name(*[2])!=name(*[3]) 
    and name(*[1])!=name(*[3]) 
    and not(*[position() > 3][name()!=name(preceding-sibling::*[3])])" 

如果交错是完美的(或者如果只有三个项目),则返回true。

编辑:添加第一个条件以确保最终的元组完成,并确保三个中间条件以确保重复元组包括三个项目(即不包含重复项)中的每一个。

+0

如果元组包含重复项,则这会错误地测试true。 – JPM

0

前提是元组的顺序是固定的,这个模板将针对有1个或多个元组否则为false所有情况下返回true:

<xsl:template match="t"> 
    <xsl:sequence 
    select=" 
    count(*) gt 2 and 
    count(*) = count(*[ 
     self::cat and position() mod 3 = 1 or 
     self::dog and position() mod 3 = 2 or 
     self::horse and position() mod 3 = 0])"/> 
</xsl:template> 

如果元组的顺序可以改变,这模板将针对存在被订购的相同元组的第一个实例,否则为假

<xsl:template match="t"> 
    <xsl:variable name="cat.pos" select="(count(cat[1]/preceding-sibling::*) + 1) mod 3"/> 
    <xsl:variable name="dog.pos" select="(count(dog[1]/preceding-sibling::*) + 1) mod 3"/> 
    <xsl:variable name="horse.pos" select="(count(horse[1]/preceding-sibling::*) + 1) mod 3"/> 
    <xsl:sequence 
    select=" 
    count(*) gt 2 and 
    count(*) = count(*[ 
     self::cat and position() mod 3 = $cat.pos or 
     self::dog and position() mod 3 = $dog.pos or 
     self::horse and position() mod 3 = $horse.pos])"/> 
</xsl:template>