2008-12-10 81 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