2010-07-06 46 views
4

我在想如何檢查一個類是否具有所有具有相同姓氏的學生的XSL片段。是的,然後(做任何事情)打印「所有姓氏相同」,否則打印「所有姓氏不相同」。XSLT:如何檢查某個父節點中的某些節點是否全部相等

打印什麼真的沒什麼關係。我只是試圖爲它找到正確的邏輯。

這裏是我的示例XML:

<root> 
    <class name="Physics"> 
     <student> 
      <firstname>John</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Mary</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Ralph</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
    </class> 
    <class name="Math"> 
     <student> 
      <firstname>John</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Mary</firstname> 
      <lastname>Doe</lastname> 
      <age>21</age> 
     </student> 
     <student> 
      <firstname>Tee</firstname> 
      <lastname>Rex</lastname> 
      <age>21</age> 
     </student> 
    </class> 
</root> 

因此,對於物理課,將打印 「所有lastnames相同」。 而對於數學課,它會打印出「所有姓氏不一樣」。

(這不是我真正的XML,因爲它是束縛到一個較小的問題,所以不是我定製這個XML來表示我的問題)

任何幫助將不勝感激。

問候, Shobhit

+0

好問題(+1)。查看我的答案以獲得有效的解決方案:) – 2010-07-06 20:07:58

+0

男士們感謝您的解決方案! 我已經結束了使用Tomalak的方法。 雖然其他方法也很好,但Tomalak的解決方案非常易於理解和使用。 – bits 2010-07-06 23:09:27

回答

4

嗯。知道沒有其他關於您的問題,我會做到這一點:

<xsl:template match="class"> 
    <xsl:choose> 
    <xsl:when test=" 
     count(student[not(lastname = preceding-sibling::student/lastname)]) = 1 
    "> 
     <xsl:text>all lastnames are same</xsl:text> 
    <xsl:when> 
    <xsl:otherwise> 
     <xsl:text>all lastnames are not same</xsl:text> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

XPath表達式

student[not(lastname = preceding-sibling::student/lastname)] 

選擇所有<student>節點,其<lastname>不像是同一個類中任何一項姓氏。

在所有姓氏相同的類中,它們的計數恰好爲1(因爲第一個學生總是有一個不同於前面任何姓氏的姓)。如果計數高於1,那麼該班的一些學生有不同的姓氏。

根據上述邏輯,一個班級根本沒有學生的情況將被視爲<xsl:otherwise>個案。您可能想要以某種方式明確處理該案例。

2

這個樣式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="student"/> 
    <xsl:template match="student[1]">all lastnames are same</xsl:template> 
    <xsl:template match="student[1][lastname != ../student/lastname]" priority="1">all lastnames are not same</xsl:template> 
</xsl:stylesheet> 

結果:

<root> 
    <class name="Physics">all lastnames are same</class> 
    <class name="Math">all lastnames are not same</class> 
</root> 

注:節點組比較。

編輯:對不起,錯過@name。

編輯2:緊湊型。請注意@priority以避免錯誤恢復。

1

這種轉變:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my" 
> 
<xsl:output method="text"/> 

<xsl:key name="kstudentByName" 
    match="student" use="lastname"/> 

<my:text> 
    <text> not </text> 
</my:text> 

<xsl:variable name="vText" select="document('')/*/my:text/*"/> 

<xsl:template match="/"> 
    <xsl:variable name="vNumNames" select= 
    "count(*/*/student[generate-id() 
        = 
         generate-id(key('kstudentByName', lastname)[1]) 
        ] 
     ) 

     > 1 
    "/> 

    All names are <xsl:value-of select="$vText[$vNumNames]"/> the same. 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用產生正確的結果:

All names are not the same. 

請注意使用按鍵,這使得這種轉變更有效比比較每個名稱與所有前面的兄弟姐妹名稱的時間複雜度的二次方

相關問題