XSLT 2.0:复制和修改分支,但将源保持在原始状态

时间:2019-03-13 10:23:32

标签: xml xslt xslt-2.0

我试图在进行调整时将XML文档的一部分复制到新元素中。但是,我想将源保持其原始状态,更改应仅出现在副本中。另外,必须保留文档的所有其他部分。

这里是一个示例,它试图通过将属性change =“ true”的所有元素的内容更改为大写来实现上述目的。

XML输入

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <original>
    <element change="true">abc</element>
    <element change="false">def</element>
  </original>
  <copy/>
  <other>preserve this</other>
</root>

XSLT样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="#all" version="2.0">
  <xsl:output method="xml" encoding="UTF-8"/>

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

  <xsl:template match="/root/copy">
    <copy>
      <xsl:copy-of select="/root/original/*"/>
    </copy>
  </xsl:template>

  <xsl:template match="/root/original/element[@change='true']/text()">
    <xsl:value-of select="upper-case(.)"/>   
  </xsl:template>

</xsl:stylesheet>

当前输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <original>
    <element change="true">ABC</element>
    <element change="false">def</element>
  </original>
  <copy>
    <element change="true">abc</element>
    <element change="false">def</element>
  </copy>
  <other>preserve this</other>
</root>

但是,我当前的XSLT基本上与我想要的相反,它只将原始元素更改为大写,而将小写版本复制到“ copy”分支。

所需的输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <original>
    <element change="true">abc</element>
    <element change="false">def</element>
  </original>
  <copy>
    <element change="true">ABC</element>
    <element change="false">def</element>
  </copy>
  <other>preserve this</other>
</root>

我使用xsl:call-template进行了一些测试,但无法产生任何接近我想要的东西。

2 个答案:

答案 0 :(得分:2)

如果您希望copy包含更改后的输出,则应在模板中使用xsl:apply-templates,而不是xsl:copy-of。并且要确保original不变,您将需要一个单独的模板来执行xsl:copy-of

尝试使用此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="#all" version="2.0">
  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

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

  <xsl:template match="/root/copy">
    <copy>
      <xsl:apply-templates select="/root/original/*"/>
    </copy>
  </xsl:template>

  <xsl:template match="/root/original">
    <xsl:copy-of select="." />
  </xsl:template>

  <xsl:template match="/root/original/element[@change='true']/text()">
    <xsl:value-of select="upper-case(.)"/>   
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

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

  <xsl:template match="/root/copy">
    <copy>
  <xsl:apply-templates select="/root/original/*"/>
</copy>
  </xsl:template>

  <xsl:template match="/root/original">
    <xsl:copy-of select="." />
  </xsl:template>

  <xsl:template match="/root/original/element[@change='true']/text()">
    <xsl:value-of select="upper-case(.)"/>   
  </xsl:template>