XSLT 2.0: копировать и изменять ветку, но сохранять исходный код в исходном состоянии - PullRequest
0 голосов
/ 13 марта 2019

Я пытаюсь скопировать часть 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 ]

2 голосов
/ 13 марта 2019

Если вы хотите, чтобы 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>
0 голосов
/ 13 марта 2019
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>
...