XSLT 模板覆盖
我有一个关于 XSLT 模板覆盖的小问题。 对于我的 XML 部分:
<record>
<medication>
<medicine>
<name>penicillin G</name>
<strength>500 mg</strength>
</medicine>
</medication>
</record>
在我的 XSLT 表中,我有两个按以下顺序排列的模板:
<xsl:template match="medication">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="medicine/name">
<text>!unauthorized information!</text>
</xsl:template>
我想要做的是将 drug 元素下的所有内容复制到除“name”元素(或任何其他元素)之外的输出中。我明确定义)。 最终的 xml 将以 RAW XML 形式显示给用户。 换句话说,我想要的结果是:
<record>
<medication>
<medicine>
<text>! unauthorized information!</text>
<strength>500 mg</strength>
</medicine>
</medication>
</record>
而我得到的 XML 与输入相同,即元素没有被文本替换。 为什么第二个模板匹配没有覆盖第一个模板中的名称元素,有什么想法吗? 提前致谢
- 阿里
I have a small question regarding XSLT template overriding.
For this segment of my XML:
<record>
<medication>
<medicine>
<name>penicillin G</name>
<strength>500 mg</strength>
</medicine>
</medication>
</record>
In my XSLT sheet, I have two templates in the following order:
<xsl:template match="medication">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="medicine/name">
<text>!unauthorized information!</text>
</xsl:template>
What I want to do is to copy everything under the medication element to the output other than the "name" element (or any other element that I explicitly define). The final xml will be shown to the user in RAW XML form. In other words, the result I want is:
<record>
<medication>
<medicine>
<text>! unauthorized information!</text>
<strength>500 mg</strength>
</medicine>
</medication>
</record>
Whereas I am getting the same XML as input, i.e. without the element replaced by text. Any ideas why the second template match is not overriding the name element in the first one? Thanks in advance
--
Ali
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
模板顺序并不重要。 唯一可能考虑的情况(这是与处理器相关的)是当您遇到无法解决的冲突时,即错误情况。 在这种情况下,XSLT 处理器通过选择最后出现的错误来从错误中恢复是合法的。 但是,您永远不应该编写依赖于此行为的代码。
就您而言,模板优先级甚至不是问题。 您有两种不同的模板规则,一种匹配
元素,一种匹配
元素。 它们永远不会发生冲突,因此这不是模板优先级或覆盖的问题。 问题是您的代码实际上从未将模板应用于
元素。 当您对
说
时,您是在说:“执行 <代码><药物>”。 任何模板规则对后代节点触发的唯一方法是显式应用模板(使用
)。我为您提供的解决方案基本上与alamar 的不同之处在于它使用单独的处理“模式”,该模式将规则与样式表中的所有其他规则隔离开来。递归地应用于子节点(和属性),这使您有机会覆盖某些节点的行为。
“
medicine/name
”的规则将覆盖“@* | node(”的规则。 )
”,因为模式的格式(包含“/
”)使其默认优先级(0.5)高于“node()" (-1.0)。
关于模板优先级如何工作的完整而简洁的描述可以在 "How XSLT Works” 在我的网站上。
最后,我注意到您提到要向用户显示“RAW XML”。 例如,这是否意味着您想要在浏览器中显示带有所有开始和结束标记的 XML? 在这种情况下,您需要转义所有标记(例如,“
<
”表示“<
”)。 查看我网站上的 XML 转字符串实用程序。 如果您需要如何使用它的示例,请告诉我。Template order does not matter. The only case it possibly becomes considered (and this is processor-dependent) is when you have an un-resolvable conflict, i.e. an error condition. In that case, it's legal for the XSLT processor to recover from the error by picking the one that comes last. However, you should never write code that depends on this behavior.
In your case, template priority isn't even the issue. You have two different template rules, one matching
<medication>
elements and one matching<name>
elements. These will never collide, so it's not a question of template priority or overriding. The issue is that your code never actually applies templates to the<name>
element. When you say<xsl:copy-of select="."/>
on<medication>
, you're saying: "perform a deep copy of<medication>
". The only way any of the template rules will fire for descendant nodes is if you explicitly apply templates (using<xsl:apply-templates/>
.The solution I have for you is basically the same as alamar's, except that it uses a separate processing "mode", which isolates the rules from all other rules in your stylesheet. The generic
match="@* | node()"
template causes template rules to be recursively applied to children (and attributes), which gives you the opportunity to override the behavior for certain nodes.The rule for "
medicine/name
" overrides the rule for "@* | node()
", because the format of the pattern (which contains a "/
") makes its default priority (0.5) higher than the default priority of "node()
" (-1.0).A complete but concise description of how template priority works can be found in "How XSLT Works" on my website.
Finally, I noticed you mentioned you want to display "RAW XML" to the user. Does that mean you want to display, for example, the XML, with all the start and end tags, in a browser? In that case, you'd need to escape all markup (e.g., "
<
" for "<
"). Check out the XML-to-string utility on my website. Let me know if you need an example of how to use it.添加
到您的
并完全删除
!Add
to your
<xsl:template match="medicine/name">
And remove
<xsl:template match="medication">
altogether!