为什么模板模式中不允许使用后代或自我::? [英] Why descendant-or-self:: is not allowed in template pattern?
问题描述
假设我有以下 XML(它是 TEI 注释方案转换为 HTML):
<p>(例如,参见 <bibl type="journal" xmlns="http://www.tei-c.org/ns/1.0"><author>GregerIH 等人</author><date>2007</date>,<title>Trends Neurosci.</title><biblScope type="vol">30</biblScope> (</biblScope>biblScope type="issue">8</biblScope>):<biblScope type="pp">407-16</biblScope></bibl>).</p>
>
现在我想将所有注释节点按原样复制到生成的 XHTML 中,但只将
重命名为
(因为
只允许在 中),所以我使用了以下转换:
<xsl:variable name="nodeName"><xsl:when test="name() = 'title'">bibTitle</xsl:when><xsl:otherwise><xsl:value-of select="name()"/></xsl:otherwise></xsl:选择></xsl:变量><!-- 命名空间的改变发生在这里,但我们不在乎--><xsl:element name="{$nodeName}"><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:element></xsl:模板><xsl:template match="p/text()|tei:bibl//text()"><xsl:copy-of select="."/></xsl:模板>
但是它无法编译并因以下错误而中断:
在匹配模式中只允许 child:: 和 attribute:: 轴!违规轴 = 后代或自我
当我将匹配规则更改为 <xsl:template match="tei:bibl|tei:bibl//*">
时,它开始按预期工作.但这应该与 descendant-or-self::*
相同,对吗?我在这里遇到了转换器实现限制吗?
首先,我使用 Mozilla 3.5 内部转换器进行了测试,然后使用 Xalan 2.7.1 进行了测试 - 结果相同.
此限制仅对模板匹配模式中的任何位置步骤有效强>.这是设计使然(由 W3C XSLT 1.0 和XSLT 2.0 规范) -- 确保高效的 XSLT 处理.
注意:可以在任何位置步骤之后的谓词中自由使用任何轴(包括descending-or-self::
).
更新:
以下是在 xsl:template
的 match
属性中使用 descendant-or-self::
轴的简短完整示例:
<xsl:output omit-xml-declaration="yes" indent="yes"/><xsl:strip-space elements="*"/><xsl:template match="node()|@*"><xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy></xsl:模板><xsl:template match="num[descendant-or-self::num > 5]"/></xsl:stylesheet>
当此转换应用于以下 XML 文档时:
<num>1</num><num>2</num><num>3</num><num>4</num><num>5</num><num>6</num><num>7</num><num>8</num><num>9</num><num>10</num></nums>
想要的结果:删除值 >= 5 的任何 num
个元素:
<num>1</num><num>2</num><num>3</num><num>4</num><num>5</num></nums>
Suppose I have the following XML (which is the embedding of TEI annotation scheme into HTML):
<p>(See, for example, <bibl type="journal" xmlns="http://www.tei-c.org/ns/1.0"><author>Greger IH, et al.</author> <date>2007</date>, <title>Trends Neurosci.</title> <biblScope type="vol">30</biblScope> (<biblScope type="issue">8</biblScope>): <biblScope type="pp">407-16</biblScope></bibl>).</p>
Now I want to copy all annotation nodes as is into resulting XHTML but only rename <title>
to <bibTitle>
(as <title>
is only allowed in <head>
), so I used the following transformation:
<xsl:template match="tei:bibl/descendant-or-self::*">
<xsl:variable name="nodeName">
<xsl:choose>
<xsl:when test="name() = 'title'">bibTitle</xsl:when>
<xsl:otherwise><xsl:value-of select="name()" /></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Changing of the namespace occurs here, but we don't care -->
<xsl:element name="{$nodeName}">
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="p/text()|tei:bibl//text()">
<xsl:copy-of select="." />
</xsl:template>
However it does not compile and breaks with following error:
Only child:: and attribute:: axes are allowed in match patterns! Offending axes = descendant-or-self
When I change the match rule to <xsl:template match="tei:bibl|tei:bibl//*">
it starts working as intended. But that should be identical to descendant-or-self::*
, right? Have I hit the transformer implementation limitation here?
First I've tested with Mozilla 3.5 internal transformer, then with Xalan 2.7.1 – same negative result.
This limitation is valid only for any location step within the template's match pattern. It is by design (mandated by the W3C XSLT 1.0 and XSLT 2.0 specifications) -- to ensure efficient XSLT processing.
Do note: One can freely use any axis (including descending-or-self::
) withinin the predicates that follow any location step.
Update:
Here is a short, complete example of using the descendant-or-self::
axis in the match
attribute of xsl:template
:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="num[descendant-or-self::num > 5]"/>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<nums>
<num>1</num>
<num>2</num>
<num>3</num>
<num>4</num>
<num>5</num>
<num>6</num>
<num>7</num>
<num>8</num>
<num>9</num>
<num>10</num>
</nums>
the wanted result: any num
elements with value >= 5 are deleted:
<nums>
<num>1</num>
<num>2</num>
<num>3</num>
<num>4</num>
<num>5</num>
</nums>
这篇关于为什么模板模式中不允许使用后代或自我::?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!