模板顺序无关紧要。唯一可能考虑的情况(这取决于处理器)是当您遇到无法解决的冲突时,即错误情况。在这种情况下,XSLT 处理器通过选择最后出现的错误从错误中恢复是合法的。但是,您永远不应该编写依赖于这种行为的代码。
在您的情况下,模板优先级甚至不是问题。您有两种不同的模板规则,一种是匹配<medication>
元素,一种是匹配<name>
元素。这些永远不会发生冲突,所以这不是模板优先级或覆盖的问题。问题是您的代码实际上从未将模板应用于<name>
元素。当您说<xsl:copy-of select="."/>
on 时<medication>
,您是在说:“执行深拷贝<medication>
”。为后代节点触发任何模板规则的唯一方法是显式应用模板(使用<xsl:apply-templates/>
.
我为您提供的解决方案与 alamar 的解决方案基本相同,只是它使用单独的处理“模式”,它将规则与样式表中的所有其他规则隔离开来。通用match="@* | node()"
模板导致模板规则递归地应用于子节点(和属性),这使您有机会覆盖某些节点的行为。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- ...placeholder for the rest of your code... -->
<xsl:template match="/record">
<record>
<xsl:apply-templates/>
</record>
</xsl:template>
<!-- end of placeholder -->
<xsl:template match="medication">
<!-- Instead of copy-of, whose behavior is to always perform
a deep copy and cannot be customized, define your own
processing mode. Rules with this mode name are isolated
from the rest of your code. -->
<xsl:apply-templates mode="copy-medication" select="."/>
</xsl:template>
<!-- By default, copy all nodes and their descendants -->
<xsl:template mode="copy-medication" match="@* | node()">
<xsl:copy>
<xsl:apply-templates mode="copy-medication" select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- But replace <name> -->
<xsl:template mode="copy-medication" match="medicine/name">
<text>!unauthorized information!</text>
</xsl:template>
</xsl:stylesheet>
“ medicine/name
”的规则覆盖了“ ”的规则@* | node()
,因为模式的格式(包含“ /
”)使其默认优先级(0.5)高于“ node()
”的默认优先级(-1.0)。
关于模板优先级如何工作的完整而简明的描述可以在我的网站上的“XSLT 工作原理”中找到。
最后,我注意到您提到要向用户显示“RAW XML”。这是否意味着您想在浏览器中显示,例如,带有所有开始和结束标记的 XML?在这种情况下,您需要转义所有标记(例如,“ <
”代表“ <
”)。查看我网站上的XML-to-string 实用程序。如果您需要如何使用它的示例,请告诉我。