2012-01-30 30 views
3

我正在使用xpath2的索引值來返回已排序的節點序列中current()的索引。使用SAXON,排序的節點序列是唯一的,但index-of返回兩個值的序列。爲什麼index-of()在應用於一系列唯一節點時返回多個值?

這並非總是發生,只是偶爾發生,但不是因爲任何原因我能找到。有人可以解釋發生了什麼事嗎?

我已經根據例程給出這種奇怪的行爲的數據的一個例子製作了一個最小的例子。

源數據:

<data> 
<student userID="1" userName="user1"/> 
<session startedOn="01/16/2012 15:01:18"> 
</session> 
<session startedOn="11/16/2011 13:31:33"> 
</session> 
</data> 

我的XSL文件把會話節點到排序序列$ orderd在根模板的頂部:

<xsl:template match="/"> 
<xsl:variable name="nodes" as="node()*" select="/data/session"></xsl:variable> 
<xsl:variable name="orderd" as="node()*"> 
<xsl:for-each select="$nodes"> 
<xsl:sort select="xs:dateTime(xs:dateTime(concat(substring(normalize-space(@startedOn),7,4),'-',substring(normalize-space(@startedOn),1,2),'-',substring(normalize-space(@startedOn),4,2),'T',substring(normalize-space(@startedOn),12,8))) 
)" order="ascending"/> 
    <xsl:sequence select="."/> 
</xsl:for-each> 
</xsl:variable> 

因爲節點已經按照@startOn排序,但按相反的順序,序列$ orderd應該與文檔排序序列$節點相同,除了相反的順序。

當我使用for-each語句創建輸出時,我發現在使用index-of進行測試時,兩個節點看起來都是相同的。

下面的代碼用於輸出數據(和來自後立即上面的塊):

<output> 
<xsl:for-each select="$nodes"> 
<xsl:sort select="position()" order="descending"></xsl:sort> 
<xsl:variable name="index" select="index-of($orderd,current())" as="xs:integer*"></xsl:variable> 
<xsl:variable name="pos" select="position()"></xsl:variable>   
<session reverse-documentOrder="{$pos}" sortedOrder="{$index}"/> 
</xsl:for-each> 
</output> 

作爲輸出(如下所示)表示的,折射率的函數返回的序列(1, 2),這意味着它將兩個節點視爲相同。我檢查了用於對值進行排序的表達式,並生成了截然不同的日期時間字符串。

<output> 
<session reverse=documentOrder="1" 
     sortedOrder="1 2"/> 
<session reverse-documentOrder="2" 
     sortedOrder="1 2"/> 
</output> 

回答

0

文檔的index-ofhttp://www.w3.org/TR/xpath-functions/#func-index-of說:「在序列$ seqParam的項目正在開發EQ操作規則與$ srchParam比較類型xs值:untypedAtomic類型進行比較,如果他們類型xs:串。」。所以你試圖比較無類型的元素節點,這意味着它們被比較爲字符串,並且兩個session元素只有相同的空白字符串內容。這兩種方式相當於平等。

我不知道該怎麼建議,因爲我不確定你想達到什麼,但我希望以上解釋了你得到的結果。

+0

謝謝,我想我會使用index-of(在$ orderd中返回生成id($ n),generate-id(current()))。 (Gerritt Imsieke建議在Saxon的幫助列表中。) – 2012-01-30 13:16:44

+0

@DavidR:您並不需要使用'generate-id()',並且可以編寫非常簡單的'index-of()'函數,如我的答案中所示。 – 2012-01-30 14:18:45

2

不依靠generate-id() funcction,這是XSLT的功能,但不XPath函數,可以編寫在節點身份操作的簡單index-of()功能:

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

    <xsl:variable name="vNum3" select="/*/*[3]"/> 

    <xsl:variable name="vSeq" select="/*/*[1], /*/*[3], /*/*[3]"/> 

<xsl:template match="/"> 
    <xsl:sequence select="my:index-of($vSeq, $vNum3)"/> 
</xsl:template> 

<xsl:function name="my:index-of" as="xs:integer*"> 
    <xsl:param name="pSeq" as="node()*"/> 
    <xsl:param name="pNode" as="node()"/> 

    <xsl:for-each select="$pSeq"> 
    <xsl:if test=". is $pNode"> 
     <xsl:sequence select="position()"/> 
    </xsl:if> 
    </xsl:for-each> 
</xsl:function> 
</xsl:stylesheet> 

當該變換被應用上下面的XML文檔

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

想要的,正確的[R esult返回

2 3 

說明:在is運營商的應用。

+0

對於有時格式化代碼沒有縮進的令人討厭的SO錯誤,我表示歉意。 – 2012-01-30 14:17:22

相關問題