为什么此比较仅适用于整数类型ID?

时间:2012-07-16 17:42:02

标签: xml xslt xpath

我想知道语句[@id=current()/@id]只有在id是整数的情况下才能工作:

<elem id="1">
<elem id="1">

但如果我有:

<elem id="AAA">
<elem id="AAA">

它不起作用。

我的XSL失败的地方:

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                xmlns:tn="http://"
                exclude-result-prefixes="xsl xs fn tn">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="@*|node()">
        <xsl:copy> 
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy> 
    </xsl:template>

 <xsl:template match="genre/*">
        <xsl:copy>
            <xsl:apply-templates select="@*" />

            <xsl:apply-templates select="
     book[@id=current()/@id][@action='extend']                             
         [not( preceding-sibling::book[@id=current()/@id][@action='borrow'])]" />

            <xsl:for-each-group
                select="book[@id=current()/@id][@action='borrow'] 
             |   
            book[@id=current()/@id][@action='extend']
                [preceding-sibling::book[@id=current()/@id][@action='borrow']]"
                group-starting-with="book[@action='borrow']">
                <xsl:for-each select="current-group()[1]">
                    <xsl:copy>   
                        <xsl:apply-templates select="@*" />
                        <xsl:call-template name="merge-books-deeply">    
                            <xsl:with-param name="books" select="current-group()" />
                            <xsl:with-param name="name-path" select="()" />
                        </xsl:call-template>
                    </xsl:copy>
                </xsl:for-each>     
            </xsl:for-each-group>

            <xsl:apply-templates select="                             
     node()[ not( self::book[@id=current()/@id][@action=('borrow','extend')])]" />

        </xsl:copy>
    </xsl:template>

    <xsl:function name="tn:children-on-path" as="element()*">
        <xsl:param name="base" as="element()*" />   
        <xsl:param name="path" as="xs:string*" />    
        <xsl:choose>
            <xsl:when test="fn:empty($base)">
                <xsl:sequence select="()" />
            </xsl:when>
            <xsl:when test="fn:empty($path)">
                <xsl:copy-of select="$base/*" />     
            </xsl:when>
            <xsl:otherwise>
                <xsl:sequence select="tn:children-on-path(
     $base/*[name()=$path[1]],         
     $path[position() ne 1])" /> 
            </xsl:otherwise>  
        </xsl:choose>
    </xsl:function>

    <xsl:template name="merge-books-deeply">
        <xsl:param name="books" as="element()*" />
        <xsl:param name="name-path" as="xs:string*" />
        <xsl:for-each-group
            select="tn:children-on-path($books,$name-path)"
            group-by="name()">                                             
            <xsl:for-each select="current-group()[last()]" >  
                <xsl:copy>
                    <xsl:apply-templates select="@*" />
                    <xsl:call-template name="merge-books-deeply"> 
                        <xsl:with-param name="books" select="$books" />
                        <xsl:with-param name="name-path" select="$name-path,name()" />
                    </xsl:call-template>
                    <xsl:apply-templates select="text()" />        
                </xsl:copy>
            </xsl:for-each>
        </xsl:for-each-group>
    </xsl:template>

</xsl:stylesheet>

输入样本的工作地点:

<root> 
    <library id="L1">
        <genre id="a">
            <shelf1 id="1">                
                <book id="1" action="borrow">
                    <attributes>
                        <user>John</user>                    
                    </attributes>
                    <other1>y</other1>
                </book>  
                <book id="1" action="extend">
                    <attributes>
                        <user>Woo</user>           
                        <length>3</length>
                    </attributes>
                    <other2>y</other2>
                </book>  
                <book id="1" action="extend">
                    <attributes>
                        <length>2</length>
                        <condition>ok</condition>
                    </attributes>
                    <other3>y</other3>
                </book>
                <book id="2" action="extend">
                    <attributes>
                        <length>99</length>
                        <condition>not-ok</condition>
                    </attributes>
                    <other>y</other>
                </book>
            </shelf1>
            <shelf1 id="b">...
            </shelf1>

        </genre>
        <genre id="b">...
        </genre>
    </library>
</root>

如果我将图书的ID更改为1a

<root> 
    <library id="L1">
        <genre id="a">
            <shelf1 id="1">                
                <book id="1a" action="borrow">
                    <attributes>
                        <user>John</user>                    
                    </attributes>
                    <other1>y</other1>
                </book>  
                <book id="1a" action="extend">
                    <attributes>
                        <user>Woo</user>           
                        <length>3</length>
                    </attributes>
                    <other2>y</other2>
                </book>  
                <book id="1a" action="extend">
                    <attributes>
                        <length>2</length>
                        <condition>ok</condition>
                    </attributes>
                    <other3>y</other3>
                </book>
                <book id="2" action="extend">
                    <attributes>
                        <length>99</length>
                        <condition>not-ok</condition>
                    </attributes>
                    <other>y</other>
                </book>
            </shelf1>
            <shelf1 id="b">...
            </shelf1>

        </genre>
        <genre id="b">...
        </genre>
    </library>
</root>

我的错误输出:(根本不合并)

<root> 
    <library id="L1">
        <genre id="a">
            <shelf1 id="1">                
                <book id="a1" action="borrow">
                    <attributes>
                        <user>John</user>                    
                    </attributes>
                    <other1>y</other1>
                </book>  
                <book id="a1" action="extend">
                    <attributes>
                        <user>Woo</user>           
                        <length>3</length>
                    </attributes>
                    <other2>y</other2>
                </book>  
                <book id="a1" action="extend">
                    <attributes>
                        <length>2</length>
                        <condition>ok</condition>
                    </attributes>
                    <other3>y</other3>
                </book>
                <book id="2" action="extend">
                    <attributes>
                        <length>99</length>
                        <condition>not-ok</condition>
                    </attributes>
                    <other>y</other>
                </book>
            </shelf1>
            <shelf1 id="b">...
            </shelf1>

        </genre>
        <genre id="b">...
        </genre>
    </library>
</root>

预期产出:

<root> 
    <library id="L1">
        <genre id="a">
            <shelf1 id="1">                
                <book id="1a" action="borrow">
                    <attributes>
                        <user>Woo</user>           
                        <length>2</length>
                        <condition>ok</condition>                  
                    </attributes>
                    <other1>y</other1>
                </book>  
                <book id="2" action="extend">
                    <attributes>
                        <length>99</length>
                        <condition>not-ok</condition>
                    </attributes>
                    <other>y</other>
                </book>
            </shelf1>
            <shelf1 id="b">...
            </shelf1>

        </genre>
        <genre id="b">...
        </genre>
    </library>
</root>

对于每个具有action = borrow的节点,后跟一个或多个带有action = extend

的节点
  • 将其合并到具有action = borrow的节点。

  • 将子属性合并在一起,使其具有最新值的兄弟姐妹的所有唯一属性。

  • 保持其他孩子不变

合并仅发生在具有相同ID的节点上。

感谢。 问候, 约翰

2 个答案:

答案 0 :(得分:3)

也许您遇到了上下文问题。比较应该有效。这是一个例子......

XML输入

<tests>
    <test>
        <elem id="1"/>
        <elem id="1"/>
    </test>
    <test>
        <elem id="AAA"/>
        <elem id="AAA"/>
    </test>
    <test>
        <elem id="BBB"/>
        <elem id="CCC"/>
    </test>
    <test>
        <elem id="2"/>
        <elem id="3"/>
    </test>
</tests>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:template>

    <xsl:template match="elem[1]">
        <xsl:text>Comparing id </xsl:text>
        <xsl:value-of select="concat('&quot;',@id,'&quot;&#xA;')"/>
        <xsl:value-of select="concat('&#x9;',
            boolean(following-sibling::*[@id=current()/@id]),
            '&#xA;')"/>
    </xsl:template>

</xsl:stylesheet>

<强>输出

Comparing id "1"
    true
Comparing id "AAA"
    true
Comparing id "BBB"
    false
Comparing id "2"
    false

修改

在查看更新后的示例后,它看起来肯定是一个上下文问题。看一下模板的开头:

<xsl:template match="genre/*">
        <xsl:copy>
            <xsl:apply-templates select="@*" />

            <xsl:apply-templates select="
     book[@id=current()/@id][@action='extend']                             
         [not( preceding-sibling::book[@id=current()/@id][@action='borrow'])]" />

请注意,匹配为genre/*;这是当前的背景。您的输入将是shelf1。然后,第二个xsl:apply-templates的选择以book[@id=current()/@id]开头。对我来说,如果它book属性等于id id属性,则会选择shelf1。要对此进行测试,您还可以将id的{​​{1}}更改为shelf1,这可能会有效。 (这就是第一个例子有效的原因; 1aid的{​​{1}}匹配。

我现在无法测试这个理论,但我认为这就是比较不起作用的原因。 (它正在运作,你只是没有比较你认为你在比较的东西。)

答案 1 :(得分:1)

字符串比较不需要显式字符串转换。换句话说,它应该像你写的一样工作。这是一个例子:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="elem">
    <xsl:if test="count(../elem[@id=current()/@id]) &gt; 1">
      <xsl:value-of select="@id"/>: has dup
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

应用于此输入时:

<r>
    <elem id="AAA">one</elem>
    <elem id="AAA">two</elem>
    <elem id="ZZZ">three</elem>
</r>

生成以下输出:

AAA: has dup
AAA: has dup

来自the XPath spec

  

否则,如果要比较的对象中至少有一个是数字,那么   将要比较的每个对象转换为数字,就像通过应用一样   数字功能。否则,要比较的两个对象都是   通过应用字符串函数转换为字符串。