xpath : 测试节点是否是指定 ok 元素以外的唯一子节点
xpath : test if node is the only child other than specified ok elements
我想编写一个 xsl 模板来检查给定节点是否是唯一的子节点,而不是某些指定的元素:
在此示例中, 将更改为 ,因为它是唯一的 节点,并且只有 节点在它之前
<root>
<!-- this is ok, the ok nodes are at the top, followed by only 1 target -->
<mynode>
<ok1/>
<ok2/>
<target/>
</mynode>
<!-- will fail, bad element before target -->
<mynode>
<ok1/>
<ok2/>
<bad/>
<target/>
</mynode>
<!-- no match, multiple target nodes -->
<mynode>
<ok1/>
<ok2/>
<target/>
<target/>
</mynode>
</root>
我正在使用这个 xpath:
<xsl:template match="target[not(following-sibling::*)]
[not(preceding-sibling::target)]
[not(preceding-sibling::*[starts-with(name(), 'bad' or 'hello')])]
">
<hit>
<xsl:apply-templates/>
</hit>
</xsl:template>
在最后一个谓词中,我是否必须特别指出我不想要的任何节点?我可以这样吗
not(preceding-sibling::*[not(starts-with(name(), 'ok'))])
谢谢
[not(preceding-sibling::*[starts-with(name(), 'bad' or 'hello')])]
将不起作用,因为 'bad' 或 'hello' 是布尔值或字符串
您也不需要使用 double not()
然后简单地做
preceding-sibling::*[starts-with(name(),'ok')]
您还可以创建白名单或黑名单并使用 contains() XPath 函数对其进行迭代,例如:
<xsl:variable name="oks" select="ok1 ok2 ok3"/>
然后匹配
preceding-sibling::*[contains($oks, name())]
这个怎么样:
<xsl:template match="target[count(../*) =
count(../*[starts-with(name(), 'ok')]) + 1]">
<hit>
<xsl:apply-templates/>
</hit>
</xsl:template>
解释是匹配target
if:
- 其父元素的所有子元素个数等于
- 其父元素的所有好子元素的个数加一(自身)
Edit 如果您只想匹配元素是其父元素的 last 子元素(您在您的问题,但您的示例表明),您可以将 and not(following-sibling::*)
添加到上面的谓词中,或者这是另一种方法:
<xsl:template match="target[not(following-sibling::*) and
not(preceding-sibling::*[not(starts-with(name(), 'ok'))])
]">
但你似乎已经自己想出了一个办法。
最后,如果您真正想要做的是允许某些特定的 OK 元素并且不匹配基于前缀的名称,您可以为此使用 self::
:
<xsl:template match="target[count(../*) =
count(../*[self::allgood or self::great]) + 1]">
<xsl:template match="target[not(following-sibling::*) and
not(preceding-sibling::*[not(self::allgood or
self::great )]
)]">
我想编写一个 xsl 模板来检查给定节点是否是唯一的子节点,而不是某些指定的元素:
在此示例中,
<root>
<!-- this is ok, the ok nodes are at the top, followed by only 1 target -->
<mynode>
<ok1/>
<ok2/>
<target/>
</mynode>
<!-- will fail, bad element before target -->
<mynode>
<ok1/>
<ok2/>
<bad/>
<target/>
</mynode>
<!-- no match, multiple target nodes -->
<mynode>
<ok1/>
<ok2/>
<target/>
<target/>
</mynode>
</root>
我正在使用这个 xpath:
<xsl:template match="target[not(following-sibling::*)]
[not(preceding-sibling::target)]
[not(preceding-sibling::*[starts-with(name(), 'bad' or 'hello')])]
">
<hit>
<xsl:apply-templates/>
</hit>
</xsl:template>
在最后一个谓词中,我是否必须特别指出我不想要的任何节点?我可以这样吗
not(preceding-sibling::*[not(starts-with(name(), 'ok'))])
谢谢
[not(preceding-sibling::*[starts-with(name(), 'bad' or 'hello')])]
将不起作用,因为 'bad' 或 'hello' 是布尔值或字符串 您也不需要使用 double not() 然后简单地做
preceding-sibling::*[starts-with(name(),'ok')]
您还可以创建白名单或黑名单并使用 contains() XPath 函数对其进行迭代,例如:
<xsl:variable name="oks" select="ok1 ok2 ok3"/>
然后匹配
preceding-sibling::*[contains($oks, name())]
这个怎么样:
<xsl:template match="target[count(../*) =
count(../*[starts-with(name(), 'ok')]) + 1]">
<hit>
<xsl:apply-templates/>
</hit>
</xsl:template>
解释是匹配target
if:
- 其父元素的所有子元素个数等于
- 其父元素的所有好子元素的个数加一(自身)
Edit 如果您只想匹配元素是其父元素的 last 子元素(您在您的问题,但您的示例表明),您可以将 and not(following-sibling::*)
添加到上面的谓词中,或者这是另一种方法:
<xsl:template match="target[not(following-sibling::*) and
not(preceding-sibling::*[not(starts-with(name(), 'ok'))])
]">
但你似乎已经自己想出了一个办法。
最后,如果您真正想要做的是允许某些特定的 OK 元素并且不匹配基于前缀的名称,您可以为此使用 self::
:
<xsl:template match="target[count(../*) =
count(../*[self::allgood or self::great]) + 1]">
<xsl:template match="target[not(following-sibling::*) and
not(preceding-sibling::*[not(self::allgood or
self::great )]
)]">