这种转变说明了如何使用全局参数(内置元素在这里模拟)指定(可能是多个)更新:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" >
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:updates>
<update place="Berlin" dt="11-Dec-2011"/>
</my:updates>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"location
[place = document('')/*/my:updates/update/@place]
/dt/text()
">
<xsl:value-of select=
"document('')/*/my:updates/update
[@place = current()/../../place]
/@dt
"/>
</xsl:template>
</xsl:stylesheet>
当所提供的XML文档应用(更正为使其成为合格的):
<Locations>
<location>
<place>Newyork</place>
<dt>01-Dec-2011</dt>
</location>
<location>
<place>Berlin</place>
<dt>02-Dec-2011</dt>
</location>
<location>
<place>Tokyo</place>
<dt>04-Dec-2011</dt>
</location>
</Locations>
想要的,正确的结果产生:
<Locations>
<location>
<place>Newyork</place>
<dt>01-Dec-2011</dt>
</location>
<location>
<place>Berlin</place>
<dt>11-Dec-2011</dt>
</location>
<location>
<place>Tokyo</place>
<dt>04-Dec-2011</dt>
</location>
</Locations>
说明:
身份规则副本的每个节点 “原样”。
只是有一个压倒一切的模板 - 匹配任何dt
其place
兄弟姐妹的字符串值的文本节点的孩子有一个相应的my:updates/update
元素。在此模板中,我们输出此对应my:updates/update
元素的dt
属性的值。
请注意:在真实世界的改造内嵌my:updates
元素将通过外部,全球参数更好的替代。阅读XSLT处理器的文档,了解如何将外部参数传递给转换 - 这取决于实现。
UPDATE:由于OP已经发现很难用全局的,外部通过xsl:param
这个解决方案的一个转换,这里是经过改装的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pUpdates">
<update place="Berlin" dt="11-Dec-2011"/>
</xsl:param>
<xsl:variable name="vUpdates" select=
"ext:node-set($pUpdates)/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dt/text()">
<xsl:choose>
<xsl:when test="../../place=$vUpdates/@place">
<xsl:value-of select=
"$vUpdates[@place = current()/../../place]/@dt"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
当这种转变是在相同的应用XML文档(上图),同样正确的,想要的结果产生:
<Locations>
<location>
<place>Newyork</place>
<dt>01-Dec-2011</dt>
</location>
<location>
<place>Berlin</place>
<dt>11-Dec-2011</dt>
</location>
<location>
<place>Tokyo</place>
<dt>04-Dec-2011</dt>
</location>
</Locations>
请注意:在此解决方案中xsl:param
仍然具有硬编码的值,这是我们使用ext:node-set()
扩展功能的唯一原因。如果参数确实是从外部传递的,那么从RTF到普通树的这种转换不是必需的,并且应该直接引用该参数。
此外,在XSLT 1.0中,我们必须更加不精确地匹配,并在模板正文内使用比较(xsl:choose
)。这是因为在XSLT 1.0中,不允许在匹配模式内引用变量/参数。
在XSLT 2.0这一限制已经消除,所以我们可以只是有一个更简单的转换:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pUpdates">
<update place="Berlin" dt="11-Dec-2011"/>
</xsl:param>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"location[place=$pUpdates/*/@place]/dt/text()">
<xsl:value-of select=
"$pUpdates/*[@place = current()/../../place]/@dt"/>
</xsl:template>
</xsl:stylesheet>
问得好,+1。覆盖身份规则并将更新作为外部参数传递给转换 - 是解决此问题的最简单和最强大的解决方案。 –
@ Dimitre-正确地说,并感谢很多:) – John