2008-12-10 112 views
5

對於我正在編寫的樣式表(實際上是一組樣式表,每個樣式表都會生成不同的輸出格式),我需要評估某個值是否存在於值列表中。在這種情況下,被測試的值取自一個元素的屬性。要測試的列表來自樣式表的調用,並且被視爲頂級<xsl:param>(當我調用xsltproc或與Saxon等價的調用時,將在命令行中提供)。例如,輸入值可以是:元素列表測試

v0_01,v0_10,v0_99 

而屬性值將每個看起來非常像一個這樣的值。 (是否用逗號分隔值或空格不重要 - 我現在選擇了一個逗號,因爲我打算通過命令行開關將值傳遞給xsltproc,並且使用空格需要引用該參數,而我很懶 - 足以不想輸入額外的兩個字符)。

我在找的東西類似於Perl的grep,其中我可以看到當前的值是否包含在列表中。它可以通過子字符串測試來完成,但是這必須是巧妙的,以免得到假陽性(v0_01不應該與包含v0_011的字符串匹配)。似乎XSL/XSLT支持的唯一非標量數據類型是節點集。我認爲有可能將列表轉換爲一組文本節點,但即使與使用額外邊界進行子字符串測試(檢查以防止錯誤匹配)相比,這似乎也是過度殺手。

回答

8

實際上,使用XPath字符串函數是正確的方法。所有你必須確定的是你測試的分隔符以及:

contains(concat(',' $list, ','), concat(',', $value, ',')) 

會返回一個布爾值。或者您可以使用其中的一個:

substring-before(concat('|,' $list, ',|'), concat(',', $value, ',')) 

substring-after(concat('|,' $list, ',|'), concat(',', $value, ',')) 

如果你得到一個空字符串作爲結果,$value不在列表中。

編輯:

@ Dimitre的評論是正確的:substring-before()(或substring-after())也將返回空字符串,如果找到字符串在列表中的第一個(或最後一個)。爲了避免這種情況,我在列表的開始和結尾添加了。仍然是這樣做的推薦方式。

+0

其實名單

        exists(tokenize($list, ',')[. = $value])

評估爲true(),我的目的,它看起來像「包含」功能會做(使用你建議的填充)。讓我感到困惑的是,我一直在尋找XPath,在XSLT本身中尋找這個功能。 – rjray 2008-12-10 14:20:24

+0

添加了contains()函數,該函數已經逃脫了我。謝謝。 :-) – Tomalak 2008-12-10 14:29:32

4

除了由託默勒格提供的XPath 1.0中的溶液,

使用XPath 2。0可以令牌化值列表:當且僅當$value包含在值$list