用 XSLT 替换节点文本? [英] Replacing the Node text with XSLT?

查看:18
本文介绍了用 XSLT 替换节点文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的XML文件,用于存储数据-

Below is my XML file, which is used to stored the data -

<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>

我想要实现的是-

如果访问被重新安排,我想替换

标记日期值.例如-如果柏林的访问日期更改,存储在 <dt> 标签中,那么如何编辑/替换相同的在 XML 文件中使用 XSLT ..?提前致谢 - 约翰

I want to replace the <dt> tags date value, if the visit is re-scheduled. For example- If the visit date for Berlin is changed, stored in <dt> tags, then how to edit/replace the same in the XML file using XSLT..? Thanks in advance - John

推荐答案

此转换展示了如何使用全局参数(此处使用内联元素建模)来指定(可能是多个)更新:

<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 文档时(已更正以使其格式正确):

When applied on the provided XML document (corrected to make it well-formed):

<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>

说明:

  1. 身份规则按原样"复制每个节点.

只有一个覆盖模板 -- 匹配任何 dt 的文本节点子节点,其 place 兄弟的字符串值具有相应的 my:updates/update 元素.在此模板中,我们输出此对应 my:updates/update 元素的 dt 属性的值.

There is just one overriding template -- matching the text-node child of any dt whose place sibling's string value has a corresponding my:updates/update element. In this template we output the value of the dt attribute of this corresponding my:updates/update element.

请注意:在现实世界的转换中,内联 my:updates 元素将更好地替换为外部全局参数.阅读您的 XSLT 处理器的文档,了解如何将外部参数传递给转换——这取决于实现.

Do note: In a realworld transformation the inline my:updates element will be better replaced by an external, global parameter. Read your XSLT processor's documentation how to pass an external parameter to the transformation -- this is implementation-dependent.

更新:由于 OP 发现很难将此解决方案转换为使用全局、外部传递的 xsl:param 的解决方案,这里是转换后的解决方案:

UPDATE: As the OP has found it difficult to convert this solution to one using global, externally passed xsl:param, here is this converted solution:

<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到正则树的转换是没有必要的,直接引用参数即可.

Do note: In this solution the xsl:param still has its value hardcoded and this is the only reason we are using the ext:node-set() extension function. If the parameter is really passed from outside, then this convertion from RTF to a regular tree isn't necessary and the parameter should be referenced directly.

此外,在 XSLT 1.0 中,我们必须更不精确地匹配,并在模板主体内使用比较(xsl:choose).这是因为在 XSLT 1.0 中不允许在匹配模式中引用变量/参数.

Also, in XSLT 1.0 we have to match more inexactly and to use comparisons (the xsl:choose) inside the body of the template. This is so because in XSLT 1.0 it isn't allowed to reference variables/parameters inside the match-pattern.

在 XSLT 2.0 中,这个限制已经消除,所以我们可以有一个更简单的转换:

In XSLT 2.0 this limitation has been eliminated, so we can just have a much simpler transformation:

<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>

这篇关于用 XSLT 替换节点文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆