2011-11-04 178 views
3

下面是我的XML文件,它是用来存储数据 -用XSLT替换节点文本?

<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>标签日期值,如果访问的是重调度。例如 - 如果柏林的访问日期被更改,存储在<dt>标记中,那么如何使用XSLT在XML文件中编辑/替换相同的 ..?在此先感谢约翰 -

+0

问得好,+1。覆盖身份规则并将更新作为外部参数传递给转换 - 是解决此问题的最简单和最强大的解决方案。 –

+0

@ Dimitre-正确地说,并感谢很多:) – John

回答

5

这种转变说明了如何使用全局参数(内置元素在这里模拟)指定(可能是多个)更新

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

说明

  1. 身份规则副本的每个节点 “原样”。

  2. 只是有一个压倒一切的模板 - 匹配任何dtplace兄弟姐妹的字符串值的文本节点的孩子有一个相应的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> 
+0

非常感谢..一个非常清晰和简洁的解释。帽子给你:) – John

+0

所以,当传递参数,我将不得不使用下面的标签 -/'和''并且将在''标记中使用这些参数。对..? – John

+0

我收到以下错误 - – John

2

身份模板将复制文件:

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

然后你就可以只为要更改的部分做其他模板。

例(未经测试):

<xsl:template match="//location/dt[preceding-sibling::place='Berlin']"> 
    <dt>Your date</dt> 
</xsl:template> 
+0

@ Krab-非常感谢:) – John

1

真正的问题是,你如何,如果访问被重新安排要检查?我看到它的方式,你有三种选择:

  • 商店重新安排日期与地点在二级XML和使用XPath document功能,从中读取数据;
  • 以编程方式生成XSLT样式表,其中已包含更正或者使用XSLT扩展函数或扩展元素(函数可能就足够)以某种其他语言执行检查。例如Java。

编辑 - 或者按照Krab的优秀建议:使用XSLT参数,让数据传递到静态样式表。

+1

嘿,怎样样式表参数 - 只是通过它的地方和新的日期。 – Krab

+0

@Krab当然......我真的应该记住你可以通过params。谁知道我已经完成的疯狂样式表可能已经被避免。将编辑。 –

+0

@ Krab-非常感谢...约翰 – John