2011-06-18 169 views
5

我相信這是一個容易的但我只是不看樹的木材。如何計算具有相同屬性值的元素

我有一個XML看起來像這樣:

<root> 
    <profil> 
     <e1 a="2">1</e1> 
     <m1 a="3">1</m1> 
     <e2 a="4">1</e2> 
     <m2 a="5">1</m2> 
    </profil> 
    <profil> 
     <e1 a="5">1</e1> 
     <m1 a="3">1</m1> 
     <e2 a="4">1</e2> 
     <m2 a="4">1</m2> 
    </profil> 
    <profil> 
     <e1 a="7">1</e1> 
     <m1 a="7">1</m1> 
     <e2 a="4">1</e2> 
     <m2 a="2">1</m2> 
    </profil> 
</root> 

現在我想知道/ M/@一個多少都等於E */@一元/ PROFIL。所以,我想出了下面的XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="*"> 
     <xsl:element name="root"> 
      <xsl:for-each select="/root/profil"> 
       <xsl:element name="count"> 
        <xsl:value-of select="count(*[contains(name(), 'm') and ./@a = //*[contains(name(),'e')]/@a])"/> 
       </xsl:element> 
      </xsl:for-each> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

但結果是錯誤的:

<root> 
    <count>1</count> 
    <count>1</count> 
    <count>2</count> 
</root> 

應該

<root> 
    <count>0</count> 
    <count>1</count> 
    <count>1</count> 
</root> 

有沒有人有一個建議,我做錯了什麼?

+0

+1爲好問題。 –

+0

好問題,+1。請參閱我的答案,以獲得一個完整,簡短且容易的解決方案,該解決方案在您的案例標準XPath函數中使用最合適的方法:'starts-with()'。 :) –

+0

我已更改標題以更好地匹配您的問題的內容。如果你關心它,可以自由地恢復到原來的狀態。 –

回答

6

更換的XPath與正確的,那就是:

<xsl:value-of select="count(*[substring(name(),1,1)='m' 
     and ./@a = ../*[substring(name(),1,1)='e']/@a])"/> 

我用substring到位的contains第一屬性特徵相匹配字符串中的任何字符相匹配。

+0

不錯的答案 - 我認爲'substring'可能比'contains'更有效率,你打敗了我:) +1 – cordsen

+0

完美,甚至更好。謝謝 – Sdudda

1

我覺得這是你所需要的

count(*[contains(name(), 'm') and (@a = parent::*/*[contains(name(),'e')]/@a)]) 

在XSLT使用該

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="*"> 
     <xsl:element name="root"> 
      <xsl:for-each select="/root/profil"> 
       <xsl:element name="count"> 
        <xsl:value-of select="count(*[contains(name(), 'm') and (@a = parent::*/*[contains(name(),'e')]/@a)])"/> 
       </xsl:element> 
      </xsl:for-each> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

產生所需的輸出

<root> 
    <count>0</count> 
    <count>1</count> 
    <count>1</count> 
</root> 
+0

也謝謝你!作品也很完美,因爲我很遺憾,我只是想長期看看這個XSLT。 – Sdudda

+0

+1正確答案 –

0

使用(與當前節點的任何profil元素):

count(*[starts-with(name(),'m') 
     and 
     @a = ../*[starts-with(name(),'e')]/@a 
     ] 
    ) 

以及完整的XSLT代碼

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="profil"> 
    <count> 
    <xsl:value-of select= 
    "count(*[starts-with(name(),'m') 
      and 
      @a = ../*[starts-with(name(),'e')]/@a 
      ] 
     ) 
    "/> 
    </count> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<root> 
    <profil> 
     <e1 a="2">1</e1> 
     <m1 a="3">1</m1> 
     <e2 a="4">1</e2> 
     <m2 a="5">1</m2> 
    </profil> 
    <profil> 
     <e1 a="5">1</e1> 
     <m1 a="3">1</m1> 
     <e2 a="4">1</e2> 
     <m2 a="4">1</m2> 
    </profil> 
    <profil> 
     <e1 a="7">1</e1> 
     <m1 a="7">1</m1> 
     <e2 a="4">1</e2> 
     <m2 a="2">1</m2> 
    </profil> 
</root> 

產生想要的,正確的結果

<count>0</count> 
<count>1</count> 
<count>1</count> 
相關問題