我无法显示第一个匹配值,例如
<test>
<p>30</p>
<p>30{1{{23{45<p>
<p>23{34</p>
<p>30{1{98</p>
</test>
<test2>
<p1>text</p1>
</test2>
所以我想循环遍历<test></test>
并找到字符串长度大于2且包含30的<p>
节点的值。我只想要第一个值。
所以我厌倦了以下代码
<xsl:variable name="var_test">
<xsl:for-each select="*/*/test()>
<xsl:if string-length(p/text())>2 and contains(p/text(),'30'))
<xsl:value-of select="xpath">
</xsl:variable>
问题是var_test始终为null。
如果我直接尝试输出任何变量
<xsl:for-each select="*/*/test()>
<xsl:if string-length(p/text())>2 and contains(p/text(),'30'))
<xsl:value-of select="xpath">
我收到以下输出
<p>30{1{23{4530{1{98</p>
但所需的输出是
<p>0{1{23{45</p>
所以我怎么能实现这个目标呢?
答案 0 :(得分:3)
使用
而不是for-each<xsl:copy-of select="(*/*/test/p[string-length() > 2 and
contains(.,'30'))] )[1]" />
[1]
仅选择第一个匹配的<p>
。 (更新:我更改了上面的XPath以回应@ markusk的评论。)
上面将输出<p>
元素及其文本内容,如“所需输出”中所示。如果您实际只想要<p>
的值,即其文字内容,请使用<xsl:value-of>
代替<xsl:copy-of>
。
<强>附录:强>
打破循环的想法不适用于XSLT,因为它不是一种过程语言。在<xsl:for-each>
循环中,循环的“第一”实例化(以文档顺序或排序顺序说话)不一定在“最后”实例化之前按时间顺序评估。它们可以以任何顺序或并行地进行评估,因为它们不相互依赖。因此,试图“突破循环”(旨在导致循环的“后续”实例化不被评估)是行不通的:如果确实如此,后续实例化的结果将依赖于早期实例化和并行评估将被排除在外。