请看以下两个例子:
<foo>some text <bar/> and maybe some more</foo>
Run Code Online (Sandbox Code Playgroud)
和
<foo>some text <bar/> and a last <bar/></foo>
Run Code Online (Sandbox Code Playgroud)
混合文本节点和bar元素内的foo元素.现在我在foo,并想知道最后一个孩子是否是一个bar.第一个例子应该被证明是假的,因为之后有文本bar,但第二个例子应该是真的.
如何使用XSLT实现这一目标?
jas*_*sso 14
只需选择<foo>元素的最后一个节点,然后使用selfaxis来解析节点类型.
/foo/node()[position()=last()]/self::bar
Run Code Online (Sandbox Code Playgroud)
如果最后一个节点不是元素,则此XPath表达式返回一个空集(等同于布尔值false).如果要专门获取值,true或者false将此表达式包装在XPath函数中boolean().使用self::*而不是self::bar匹配任何元素作为最后一个节点.
输入XML文档:
<root>
<foo>some text <bar/> and maybe some more</foo>
<foo>some text <bar/> and a last <bar/></foo>
</root>
Run Code Online (Sandbox Code Playgroud)
XSLT文档示例:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="foo">
<xsl:choose>
<xsl:when test="node()[position()=last()]/self::bar">
<xsl:text>bar element at the end </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>text at the end </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
样式表的输出:
text at the end
bar element at the end
Run Code Online (Sandbox Code Playgroud)
现在我在
foo,并想知道最后一个孩子是否是一个bar
用途:
node()[last()][self::bar]
Run Code Online (Sandbox Code Playgroud)
任何非空节点集的布尔值true()都是false(),否则就是.您可以直接使用上面的表达式(未修改)作为test任何<xsl:if>或的属性值<xsl:when>.
更好,使用:
foo/node()[last()][self::bar]
Run Code Online (Sandbox Code Playgroud)
作为一个match属性<xsl:template>- 因此你用纯粹的"推"式写作.
更新: 此答案解决了原始问题标题中所述的要求,"查明最后一个子节点是否为文本节点".但问题机构提出了不同的要求,而后者的要求似乎是OP所要求的要求.
前两个答案明确地测试最后一个子bar元素是否是元素,而不是直接测试它是否是文本节点.如果foo 仅包含"混合文本节点和条形元素" 并且永远不会有零个子元素,那么这是正确的.
但您可能想直接测试最后一个子节点是否为文本节点:
也许你知道后两种情况永远不会发生在你的情况下(但是根据你的问题我会猜到#3可以).或者也许你是这么想但不确定,或者你没有想过它.在任何一种情况下,直接测试你真正想知道的东西更安全:
test="node()[last()]/self::text()"
Run Code Online (Sandbox Code Playgroud)
因此,在@Dimitre的示例代码和输入的基础上,使用以下XML输入:
<root>
<foo>some text <bar/> and maybe some more</foo>
<foo>some text <bar/> and a pi: <?foopi param=yes?></foo>
<foo>some text <bar/> and a comment: <!-- baz --></foo>
<foo>some text and an element: <bar /></foo>
<foo noChildren="true" />
</root>
Run Code Online (Sandbox Code Playgroud)
使用此XSLT模板:
<xsl:template match="foo">
<xsl:choose>
<xsl:when test="node()[last()]/self::text()">
<xsl:text>text at the end; </xsl:text>
</xsl:when>
<xsl:when test="node()[last()]/self::*">
<xsl:text>element at the end; </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>neither text nor element child at the end; </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
收益率:
text at the end;
neither text nor element child at the end;
neither text nor element child at the end;
element at the end;
neither text nor element child at the end;
Run Code Online (Sandbox Code Playgroud)