2011-11-22 60 views
2

提供的示例是我正在嘗試做的簡化版本。在XSLT中,如何在訪問不同的XPath時訪問一個XPath?

使用XSLT,我如何比較來自不同(非-child)xpaths中節點的數據?我想比較每個cd/artistdvd/director以查看它們是否匹配(請參閱下面的示例)。有多個CD和DVD,但在這個簡單的例子中,我只使用了每一個。我試圖在一個模板中進行比較,但我無法訪問DVD xpath。我無法使用單獨的模板訪問DVD xpath。當使用單獨的模板時,我創建了一個我稱之爲「比較」模板(<xsl:call-template name="compare">)。通過訪問,我的意思是我無法打印DVD /導演的價值。

我的問題:如何在訪問不同的xpath時訪問一個xpath?我想要做的是比較光盤藝術家與DVD導演,看看他們是否匹配。並打印出這些值,如果它們匹配。我無法弄清楚的是如何讓藝術家和導演,讓我可以比較它們。我的xslt確實打印了cd的藝術家價值,但我無法打印出dvd /導演的價值。

我的樣本如下:

樣本來自W3Schools。我修改了他們來說明我的問題。

樣品XSLT

<xsl:for-each select="catalog/cd"> 
    <xsl:value-of select="@artist"/> 
    <xsl:for-each select="catalog/dvd">   
    <xsl:if test="@director = @artist"> 
     <xsl:value-of select="@director"/> 
    </xsl:if>   
    </xsl:for-each> 
</xsl:for-each> 

示例XML

<?xml version="1.0" encoding="ISO-8859-1"?> 
<catalog> 
<cd title="Unchain my heart" artist="Joe Cocker"> 

    <country>USA</country> 
    <company>EMI</company> 
    <price>8.20</price> 
    <year>1987</year> 
</cd> 

    <dvd title="My DVD Movie" director="Joe Cocker"> 
    <country>USA</country> 
    <company>WB</company> 
    <price>20.00</price> 
    <year>1999</year> 
    </dvd> 
</catalog> 

感謝您的幫助提前。

+0

這段代碼是非常錯誤的:沒有任何名稱爲'director'或'artist'的屬性。 –

+0

對不起。固定。 – user1060538

回答

1

我認爲更大的問題是,您在以程序化的方式思考,這很少是用XSLT解決問題的正確方法。更好的方法是首先匹配cd元素,然後選擇其director匹配artist的元素dvd。考慮這個樣式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="/*/cd"> 
     <xsl:value-of select="artist"/> 
     <xsl:apply-templates select="../dvd[director=current()/artist]" 
      mode="out"/> 
    </xsl:template> 
    <xsl:template match="dvd" mode="out"> 
     <xsl:value-of select="director"/> 
    </xsl:template> 
    <xsl:template match="dvd"/> 
</xsl:stylesheet> 

第一個模板適用模板其下述謂詞爲true的dvd元素:director=current()/artist

當然,在你的榜樣,我們只是在打印的名稱Joe Cocker兩次,這不是很有用。

備註:當多於一個的cd元素具有相同的artist時,此方法發生故障。更復雜的分組策略將解決這種情況。

+0

感謝您的回答。我對示例XML進行了編輯,以反映藝術家和導演的實際屬性。我將你的答案應用到我的修復中,並且工作。我更習慣於Java和類似的語言,而XSLT對我來說是新的。我仍然習慣於函數式編程。 – user1060538

0

作出這樣的:

<xsl:for-each select="/catalog/dvd"> 

沒有前導斜槓 「/」,目錄/ DVD是相對於它由<xsl:for-each select="catalog/cd">

+0

謝謝你的回答。我感謝你抽出時間。 – user1060538

0

設置當前節點, 您可以簡化您的for-each和使用current() ...

<xsl:for-each select="catalog/cd"> 
    <xsl:value-of select="artist"/> 
    <xsl:for-each select="../dvd[director = current()/artist]"> 
     <xsl:value-of select="director"/>     
    </xsl:for-each> 
</xsl:for-each> 
+0

謝謝你的回答。我感謝你抽出時間。 – user1060538

0

那麼一些指針:

<xsl:for-each select="catalog/cd"> 

當你這樣做時,你是在每個目錄/ cd元素的「內部」。因此你的current()代表eacy catalog/cd元素。

你「比較功能」:

<xsl:if test="@director = @artist"> 

,因爲你想比較屬性導演和藝術家不工作。但沒有導演和藝術家的屬性,即使他們是,你會試圖比較catalog/dvd的屬性。

所以dvd元素將不得不像<dvd director="foo" artist="bar"/>等。

我想,你真正要做的是找到CD和DVD具有相同的藝術家/導演。我不清楚你想要達到什麼。如果你詳細說明,你會得到更好的答案。

+0

是的,我解決了我的錯誤。儘管謝謝你的回答。我感謝你抽出時間。 – user1060538

+0

@ user1060538沒問題:) – FailedDev