下面是我的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>
</Location>
Run Code Online (Sandbox Code Playgroud)
我想要实现的是 -
<dt>如果重新安排访问,我想替换标签日期值.例如 - 如果更改柏林的访问日期,存储在<dt>标签中,那么如何使用XSLT编辑/替换XML文件中的相同日期.提前谢谢 - 约翰
此转换显示如何使用全局参数(此处使用内联元素建模)来指定(可能是多个)更新:
<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>
Run Code Online (Sandbox Code Playgroud)
应用于提供的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>
Run Code Online (Sandbox Code Playgroud)
产生了想要的正确结果:
<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>
Run Code Online (Sandbox Code Playgroud)
说明:
身份规则"按原样 " 复制每个节点.
只是有一个压倒一切的模板 -匹配任何文本子节点dt,其place兄弟姐妹的字符串值都有相应的my:updates/update元素.在此模板中,我们输出dt此对应my:updates/update元素的属性值.
请注意:在realworld转换中,内联my:updates元素将更好地被外部全局参数替换.阅读XSLT处理器的文档,了解如何将外部参数传递给转换 - 这取决于实现.
更新:由于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>
Run Code Online (Sandbox Code Playgroud)
当此转换应用于同一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>
Run Code Online (Sandbox Code Playgroud)
请注意:在此解决方案中,xsl:param仍然将其值设置为硬编码,这是我们使用ext:node-set()扩展功能的唯一原因.如果参数确实是从外部传递的,那么从RTF到常规树的这种转换不是必需的,应该直接引用参数.
此外,在XSLT 1.0中,我们必须更加不精确地匹配并xsl:choose在模板体内使用比较().这是因为在XSLT 1.0中,不允许在match-pattern中引用变量/参数.
在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>
Run Code Online (Sandbox Code Playgroud)