2011-08-01 39 views
5

中選擇幾個不同的元素之一我是一個有經驗的程序員,但是XSLT的新手,我發現它很莫名其妙。我很抱歉,如果這是一個問題之前已經問過,但我很受XSLT沮喪,我甚至不知道要搜索什麼...從屬性

我有一個問題,如果某個XML元素只出現有一次,我想要它的內容輸出,但是如果它出現不止一次,我只想要那些具有特定屬性的內容。

例如,假設我有一個XML文件(稱之爲 「文件1」),其包含

<food> 
    <snack>Chips</snack> 
    <snack type="nuts">Peanuts</snack> 
</food> 

和另一個XML文件( 「文件2」),其中包含

<food> 
    <snack>Cheese puffs</snack> 
</food> 

我需要一個在處理文件1時只輸出「Peanuts」(但不是「Chips」)的XSLT,但仍然爲文件2輸出「Cheese puffs」(即我不能只選擇那些具有「type」屬性的元素,那太簡單了)。

這可能是簡單的,但我堅持......

+0

好問題,+1。基於最基本和最強大的XSLT設計模式 - 重寫身份規則,查看我的答案,獲得完整,簡短和簡單的解決方案。還提供瞭解釋。 –

回答

1

這種轉變

<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="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match= 
    "*[snack/@type]/snack[not(@type)]"/> 
</xsl:stylesheet> 

產生在這兩種情況下想要的結果。

說明

  1. 身份規則/模板拷貝的每一個節點 「原樣」

  2. 第二模板重寫身份模板任何snack元件沒有type屬性已經同級具有一個type屬性snack元件。該模板具有空的主體,從而有效地將匹配的元素從被複制到輸出中「刪除」。

+0

太棒了!很棒!謝謝。從來沒有在我最瘋狂的想象中想到用兩個模板解決問題:一個幾乎與我想要的完全相反,另一個從字面上什麼都不做。爲什麼XSLT習慣用法必須如此反直覺:-) – NumerousHats

0

如果某個XML元素只出現一次,我想其內容輸出,但如果它發生不止一次,我想只有那些具有特定屬性的內容。

這方面的一個直接的翻譯是

if (count(snack) = 1) then snack else snack[@type='nuts'] 

這是有效的XPath 2.0語法 - 如果你需要做的是在1.0,然後將其轉換相當直接(雖然冗長)成等價的xsl:選擇。

如果你想要的東西,甚至比上面更簡潔,你也可以寫了XPath 2.0

(snack[@type='nuts'], snack)[1] 

它建立第一個含有類型=「堅果」,那麼所有的零食小吃的列表,然後從該列表中選擇第一個項目。