假设我有一个这样的示例XML文件,
<Entry>
<lang>
<definition>definition</definition>
<note>aaaaaaaaa
<list>
<list-item>aabbbbbbbb</list-item>
<list-item>aacccccccc</list-item>
<list-item>aadddddddd</list-item>
</list>
</note>
<example>bbbbbbbbbbb
<list>
<list-item>bbaaaaaaa</list-item>
<list-item>bbbbbbbbbbb</list-item>
<list-item>bbcccccccc</list-item>
</list>
</example>
</lang>
</Entry>
我已经写过这样的样本xsl,
<xsl:template match="Entry">
<term>
<xsl:apply-templates select="node() except definition"/>
</term>
</xsl:template>
<xsl:template match="definition">
<para type="definition">
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="lang">
<para type="Lang">
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="example">
<para type="example">
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="list">
<para type="list">
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="list-item">
<para type="list-item">
<xsl:apply-templates/>
</para>
</xsl:template>
正如我在Entry
模板中所写的那样,我需要从输出中删除<definition>
内容。 (<xsl:apply-templates select="node() except definition"/>
)。
据我所知,我可以抑制像<xsl:template match="definition"/>
这样的元素并删除内容,但在我的实际场景中我不能使用该方法。似乎except
关键字仅适用于给定节点的子元素,但不适用于上述示例的后代元素。
有任何建议如何消除<definition>
中apply-template中的xsl:template match="Entry"
? (不使用supress definition
元素或使用不同的模式)
答案 0 :(得分:0)
好吧,definition
是lang
的孩子 - 所以如果你想消除它,你需要在从lang
调用模板时这样做:
<xsl:template match="lang">
<para type="Lang">
<xsl:apply-templates select="node() except definition"/>
</para>
</xsl:template>
您现在拥有的模板应用于Entry
的所有子节点,definition
除外。但由于definition
不是Entry
的孩子,因此该例外毫无意义。
似乎
except
关键字仅适用于给定节点的子元素 但不是上面例子中的后代元素。
不,except
适用于它之前的任何节点集。
但即使我写
xsl:apply-templates select="node() except descendant::definition"
...<definition>
内容也没有 消除?
当你写:
<xsl:apply-templates select="node()">
这是缩写:
<xsl:apply-templates select="child::node()">
将except descendant::definition
添加到此是没有意义的。它相当于:
A, B, C except D
如果你写了:
,你会看到不同的结果<xsl:apply-templates select="descendant::node() except descendant::definition"/>
但这也会改变输出的结构。如果要保留原始层次结构,则必须以递归方式将模板从父级应用于子级 - 正如您所做的那样。
答案 1 :(得分:0)
你明显对处理模式产生了深刻的误解,从你对你所给出的(非常好的)答案的评论来判断。
首先,xsl:apply-templates选择一组节点,并使用最佳匹配模板规则处理每个节点。
因此<apply-templates select="node()"/>
将模板应用于表达式node()
选择的所有节点,即上下文节点的所有子节点。
现在,什么节点表达式“node()除了定义”选择?答案:除名为“定义”的子节点外的所有子节点。由于没有名为“definition”的子节点,因此它选择与表达式“node()”完全相同的节点。
你试图做的是某种“远距离行动”:你试图说“以正常方式处理这些节点,但是当你这样做时,如果你在任何时候到达节点称为“定义”,然后忽略它“。 XSLT不是这样工作的,也没有任何其他编程语言:你不能改变一些间接调用的函数或模板的效果,除非通过传递它理解的参数。您可以通过传递隧道参数获得最接近的值,但它们只会修改显式编写的模板的效果以查找这些参数。
但这是实现你想要的过于复杂的方式。有两种方法可以确保不处理定义元素:
(a)不要选择它们进行处理。您选择要进行处理的地方来自带有match =“lang”的模板,这就是您需要更改的内容。
(b)确保如果选择它们进行处理,则处理不产生输出,这意味着更改definition
元素的模板规则。