我对XSLT很新,但现在需要将它用于CMS。我已经提出了一个问题,但我会尝试描述我的问题,而不会涉及有关底层CMS的太多信息。如果您需要更多上下文来帮助我,我可以添加它。
所以我想做的就是测试我的xml的节点是否是特定节点的后代。
<xsl:if test="$currentNode::IsADescendantOf($someNode)">
Write this out.
</xsl:if>
任何想法?
提前致谢:)
答案 0 :(得分:5)
您应该使用union操作和节点集大小比较:
<xsl:if test="count($someNode|$currentNode/ancestor::*) = count($currentNode/ancestor::*)">
Write this out.
</xsl:if>
如果 $ someNode 是 $ currentNode 的祖先,$ someNode | $ currentNode / ancestor :: *将返回与$ currentNode / ancestor相同的节点集: :*(节点集没有任何双重因素)。
如果没有,由于联合,第一个节点集将比第二个节点集多一个节点。
答案 1 :(得分:2)
便携式(XPath 1.0和2.0)解决方案将是:
<xsl:if test="
$currentNode/ancestor::*[generate-id() = generate-id($someNode)]
">
Write this out.
</xsl:if>
这会走向祖先轴并检查其中的每个元素。如果(且仅当)其中一个祖先的唯一ID与唯一ID $someNode
匹配,则结果节点集不为空。
非空节点集评估为true,因此满足条件。
测试 - 找到<baz>
的后代的所有<foo>
:
<xml>
<foo>
<bar>
<baz>Test 1</baz>
</bar>
</foo>
<baz>Test 2</baz>
</xml>
和
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="/">
<xsl:variable name="someNode" select="//foo[1]" />
<!-- test each <baz> node if it has <foo> as a parent -->
<xsl:for-each select="//baz">
<xsl:if test="
ancestor::*[generate-id() = generate-id($someNode)]
">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
结果
<baz>Test 1</baz>
请注意,如果您指的是实际当前节点,就像我在for-each中所做的那样,则不需要单独的$currentNode
变量。默认情况下,所有XPath都相对于当前节点。
变体将是自上而下的方式。虽然效率较低(可能是几个数量级):
<xsl:if test="
$someNode[//*[generate-id() = generate-id($currentNode)]]
">
Write this out.
</xsl:if>
答案 2 :(得分:1)
查看XSL / XPath参考中的“祖先”轴
<xsl:if test="ancestor::*[. is $somenode]">
编辑:我和你一起学习。看看这是否有效(我希望我的系统上有我的XSL调试器: - )
答案 3 :(得分:1)
答案很简单,
你所要做的就是:
<xsl:if test="count(ancestor::somenode)>0">
...然后添加其余的
逻辑是,如果节点是somenode的后代,那么它将具有该节点中的一个或多个。
答案 4 :(得分:0)
后裔检查
最好的方法是使用descendant :: * axis。
如果您有一段XML看起来像这样,并希望匹配来自第一个<a>
节点的后代<alpha>
节点。
XML
<root>
<!-- check for descendants of the following alpha node-->
<alpha>
<!-- match the following node-->
<a>...</a>
<b>...</b>
<c>...</c>
</alpha>
<alpha>
<a>...</a>
<c>...</c>
</alpha>
</root>
XSLT
<xsl:if test="/root/alpha[1]/descendant::a[. is current()]">
祖先检查
在大多数情况下,这可能会有效。
<xsl:if test="ancestor::*[name() = $node]">
其中
<xsl:variable name="node" select="name(//alpha)"/>
如果您有多个要比较的节点,并且需要确保它是节点匹配而不是名称匹配,您可以使用generate-id()。
<xsl:variable name="node" select="generate-id(//alpha[3])"/>
<xsl:if test="ancestor::*[generate-id(.) = $node]">
比较祖先时,is
比较运算符不能被IMO使用,因为它需要一个叶子节点,并且叶子节点没有后代。
但我建议使用后代:: *轴,因为它更具可读性和灵活性。