2013-08-29 77 views
2

我有一個XML片段,如下面XSL交叉引用一個節點比較其他

<xml> 
<person> 
    <name>bob</name> 
    <holidays> 
     <visit>GB</visit> 
     <visit>FR</visit> 
    </holidays> 
</person> 
<person> 
    <name>joe</name> 
    <holidays> 
     <visit>DE</visit> 
     <visit>FR</visit> 
    </holidays> 
</person> 


<countrylist> 
    <country>GB</country> 
    <country>FR</country> 
    <country>DE</country> 
    <country>US</country> 
</countrylist> 
</xml> 

我想從列表是來countrylist所有國家或否取決於是否 那個人已經訪問該國還是沒有。因此,對於上面的XML如

Bob 
    GB Yes 
    FR Yes 
    DE No 
    US No 

Joe 
    GB No 
    FR Yes 
    DE Yes 
    US No 

這裏的輸出是我到目前爲止已經試過:

<xsl:template match="xml"> 
    <xsl:apply-templates select="person"> 
    </xsl:apply-templates> 
</xsl:template> 


<xsl:template match="person"> 
<xsl:value-of select="name"></xsl:value-of> 
    <xsl:apply-templates select="holidays"></xsl:apply-templates> 
</xsl:template> 

<xsl:template match="holidays"> 
      <xsl:variable name="v" select="holidays"></xsl:variable> 
    <xsl:for-each select="/xml/countrylist/country"> 
     <xsl:variable name="vcountry" select="."></xsl:variable> 
     <xsl:if test="$v/holidays[$vcountry]">  
     <xsl:value-of select="$vcountry"></xsl:value-of><xsl:value-of select="'*'"/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

編輯:我終於使用下面的管理;有更容易的方法嗎?

<xsl:template match="xml"> 
    <xsl:apply-templates select="person"> 
    </xsl:apply-templates> 
</xsl:template> 
<xsl:template match="person"> 
    <xsl:variable name="hols" select="holidays"/> 
    <xsl:value-of select="name"/> 
    <xsl:for-each select="/xml/countrylist/country"> 
     <xsl:variable name="vcountry" select="."/> 
     <xsl:if test="$hols[visit=$vcountry]"> 
      <xsl:value-of select="$vcountry"/> 
      <xsl:value-of select="'*'"/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

回答

1

如果你只想要顯示每個人訪問過的國家(而不是還顯示「無」,爲那些他們沒有訪問),那麼你就不需要在countrylist在涉及所有

<xsl:template match="person"> 
    <xsl:value-of select="name"/> 
    <xsl:for-each select="holidays/visit"> 
     <xsl:value-of select="." /> 
     <xsl:text> *</xsl:text> 
    </xsl:for-each> 
</xsl:template> 

如果你想在「不」的條目,然後你的方法是好的,但你可以把它簡化一下:

<xsl:template match="person"> 
    <xsl:variable name="visits" select="holidays/visit"/> 
    <xsl:value-of select="name"/> 
    <xsl:text> - </xsl:text> 
    <xsl:for-each select="/xml/countrylist/country"> 
     <xsl:value-of select="." /> 
     <xsl:choose> 
      <xsl:when test=". = $visits"> 
       <xsl:text>: Yes </xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>: No </xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
</xsl:template> 

趁着如果左邊的節點(在這種情況下爲country)的值與的任何的右邊節點(當前人的visit元素)具有相同的值,則節點和節點集之間的等值比較爲真)。

+0

非常好......謝謝伊恩。這是一個很棒的提示! – dmckinney

+0

@dmckinney當兩邊都有一個節點集時,相同的擴展就可以進行比較 - 如果左手集合中的任何節點與右邊的節點相匹配,則比較成功。這就是爲什麼'x!= y'和'not(x = y)'可以給出不同的結果 - 第一種意思是「至少有一對x和y不匹配」,而第二種意思是「存在_no_一對x和y _does_匹配「。 –