XSLT:测试兄弟是否匹配条件列表
XSLT: test if sibling matches list of conditions
我有一个条件列表,我想检查元素的直接兄弟是否符合这些条件中的任何一个。
如果这些条件是简单的标签名称,这很容易。
<xsl:param name="tag-list" select="tokenize('img figure table', '\s+')"/>
<xsl:template match="* | text()">
<xsl:variable name="next-name" select="name(following-sibling::*[1])" />
<xsl:if test="$next-name = $tag-list">
<!-- DoSomething -->
</xsl:if>
</xsl:template>
此模板将匹配任何元素或文本节点,如果该节点的紧随其后的兄弟节点是 <img>, <figure> or <table>
.
,则该模板将执行 DoSomething
但是,我想检查更复杂的条件。当模板与具有特定属性、子元素或文本值的同级元素匹配时,我如何才能只做一些事情?我更愿意使用单个 <xsl:if>
来执行此操作,因为此兄弟条件列表可能会很长。
<xsl:param name="tag-list" select="tokenize('img[@src] figure[text()] table[tbody]', '\s+')"/>
<xsl:template match="* | text()">
<xsl:if test="???">
<!-- DoSomething -->
</xsl:if>
</xsl:template>
如果您使用 XSLT 3,请考虑带有 shadow 属性的静态参数是否允许您在样式表编译之前即时构建正确的 XPath 表达式:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="tag-list" static="yes" select="tokenize('img[@src] figure[text()] table[tbody]', '\s+')"/>
<xsl:template match="* | text()">
<xsl:if _test="{string-join($tag-list ! ('following-sibling::*[1][self::' || . || ']'), ' | ')}">
<xsl:comment>DoSomething</xsl:comment>
</xsl:if>
<xsl:next-match/>
</xsl:template>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>
在 https://xsltfiddle.liberty-development.net/3NSTbf3 转换
<root>
<section><span>test</span><img src="foo.jpeg"/></section>
<section>test<table><tbody>...</tbody></table><span>test</span><figure>...</figure></section>
</root>
进入
<root>
<section><!--DoSomething--><span>test</span><img src="foo.jpeg"/></section>
<section><!--DoSomething-->test<table><tbody>...</tbody></table><!--DoSomething--><span>test</span><figure>...</figure></section>
</root>
这个例子是为了展示 _test
作为影子属性的使用,我特意使用了不同的模板内容,因为它似乎更容易显示带有身份转换和注释的代码结果在 xsl:if
开始的地方输出。
定义一个表示复杂条件的函数:
<xsl:function name="my:condition" as="xs:boolean">
<xsl:param name="node" as="node()"/>
... your condition goes here ...
</xsl:function>
然后测试是:
<xsl:if test="following-sibling::*[1][my:condition(.)]">...</xsl:if>
如果您想将条件模块化为单独的函数,那么您当然可以这样做:
<xsl:function name="my:condition" as="xs:boolean">
<xsl:param name="node" as="node()"/>
<xsl:sequence select="my:first($node) and my:second($node) and..."/>
</xsl:function>
如果你想让逻辑更动态一点,所以条件列表以某种方式动态提供,然后考虑使用高阶函数。
我有一个条件列表,我想检查元素的直接兄弟是否符合这些条件中的任何一个。
如果这些条件是简单的标签名称,这很容易。
<xsl:param name="tag-list" select="tokenize('img figure table', '\s+')"/>
<xsl:template match="* | text()">
<xsl:variable name="next-name" select="name(following-sibling::*[1])" />
<xsl:if test="$next-name = $tag-list">
<!-- DoSomething -->
</xsl:if>
</xsl:template>
此模板将匹配任何元素或文本节点,如果该节点的紧随其后的兄弟节点是 <img>, <figure> or <table>
.
但是,我想检查更复杂的条件。当模板与具有特定属性、子元素或文本值的同级元素匹配时,我如何才能只做一些事情?我更愿意使用单个 <xsl:if>
来执行此操作,因为此兄弟条件列表可能会很长。
<xsl:param name="tag-list" select="tokenize('img[@src] figure[text()] table[tbody]', '\s+')"/>
<xsl:template match="* | text()">
<xsl:if test="???">
<!-- DoSomething -->
</xsl:if>
</xsl:template>
如果您使用 XSLT 3,请考虑带有 shadow 属性的静态参数是否允许您在样式表编译之前即时构建正确的 XPath 表达式:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="tag-list" static="yes" select="tokenize('img[@src] figure[text()] table[tbody]', '\s+')"/>
<xsl:template match="* | text()">
<xsl:if _test="{string-join($tag-list ! ('following-sibling::*[1][self::' || . || ']'), ' | ')}">
<xsl:comment>DoSomething</xsl:comment>
</xsl:if>
<xsl:next-match/>
</xsl:template>
<xsl:mode on-no-match="shallow-copy"/>
</xsl:stylesheet>
在 https://xsltfiddle.liberty-development.net/3NSTbf3 转换
<root>
<section><span>test</span><img src="foo.jpeg"/></section>
<section>test<table><tbody>...</tbody></table><span>test</span><figure>...</figure></section>
</root>
进入
<root>
<section><!--DoSomething--><span>test</span><img src="foo.jpeg"/></section>
<section><!--DoSomething-->test<table><tbody>...</tbody></table><!--DoSomething--><span>test</span><figure>...</figure></section>
</root>
这个例子是为了展示 _test
作为影子属性的使用,我特意使用了不同的模板内容,因为它似乎更容易显示带有身份转换和注释的代码结果在 xsl:if
开始的地方输出。
定义一个表示复杂条件的函数:
<xsl:function name="my:condition" as="xs:boolean">
<xsl:param name="node" as="node()"/>
... your condition goes here ...
</xsl:function>
然后测试是:
<xsl:if test="following-sibling::*[1][my:condition(.)]">...</xsl:if>
如果您想将条件模块化为单独的函数,那么您当然可以这样做:
<xsl:function name="my:condition" as="xs:boolean">
<xsl:param name="node" as="node()"/>
<xsl:sequence select="my:first($node) and my:second($node) and..."/>
</xsl:function>
如果你想让逻辑更动态一点,所以条件列表以某种方式动态提供,然后考虑使用高阶函数。