我有一个包含多行数据的XML。
<abc>
<def>some text1</def>
<xyz>stack overflow</xyz>
</abc>
<abc>
<def>some text2</def>
<xyz>stack overflow 2)</xyz>
</abc>
<abc>
<def>some text</def>
<xyz>stack overflow 3)</xyz>
</abc>
现在我想在 XSL 1.0 中为此编写代码,它将开始检查每一行,即元素中的值/文本“2)”是否仅存在。 每当它在循环期间第一次遇到文本“2)”时,它应该打印“XSL_1.0 Programming”作为值并且应该退出循环。
答案 0 :(得分:2)
你以错误的方式接近这一点 - XSLT不是一种程序性语言,并且没有办法退出循环&#34;。相反,您需要考虑如何以更具说明性的方式识别您感兴趣的节点。例如XPath表达式
abc[contains(., '2)')]
标识包含字符串的所有abc
元素&#34; 2)&#34;在其后代文本节点中的任何位置,所以
(abc[contains(., '2)')])[1]
只提取第一个这样的元素,如果没有匹配的元素,则提取空节点集。如果您想处理abc
元素,包括第一个包含&#34; 2)&#34;的元素,而不是任何后续元素,您可以使用类似
<xsl:for-each select="abc[not(preceding-sibling::abc[contains(., '2)')])]">
答案 1 :(得分:1)
正如Ian Roberts所解释的那样,没有在XSLT中打破循环的概念。您必须事先决定要处理哪些节点,并且听起来您只对包含第一个 abc 元素且包含'2)'的元素感兴趣。
在这里使用 xsl:apply-templates 实际上可能更好。
<xsl:apply-templates select="abc[not(preceding-sibling::abc[contains(xyz, '2)')])]" />
因此,这将选择所有没有前面的'2)'元素的元素。
接下来,您可以添加模板以匹配 abc 元素,具体取决于 xyz 元素的内容。例如,要输出“XSL_1.0 Programming”,如果它有'2)',请执行以下操作
<xsl:template match="abc[contains(xyz, '2)')]">
<xsl:text>XSL_1.0 Programming</xsl:text>
</xsl:template>
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:apply-templates select="abc[not(preceding-sibling::abc[contains(xyz, '2)')])]" />
</xsl:template>
<xsl:template match="abc">
<xsl:value-of select="concat(xyz, ' ')" />
</xsl:template>
<xsl:template match="abc[contains(xyz, '2)')]">
<xsl:text>XSL_1.0 Programming </xsl:text>
</xsl:template>
</xsl:stylesheet>
当应用于以下XML时(注意它有一个根元素)
<root>
<abc>
<def>some text1</def>
<xyz>stack overflow</xyz>
</abc>
<abc>
<def>some text2</def>
<xyz>stack overflow 2)</xyz>
</abc>
<abc>
<def>some text3</def>
<xyz>stack overflow</xyz>
</abc>
<abc>
<def>some text</def>
<xyz>stack overflow 3)</xyz>
</abc>
</root>
以下是输出
stack overflow
XSL_1.0 Programming
答案 2 :(得分:0)
这个怎么样:
<xsl:if test="abc[contains(xyz, '2)')]">
<xsl:text>XSL_1.0 Programming</xsl:text>
</xsl:if>