использование XSL для замены узлов XML новыми узлами

Мне нужно решение XSL заменить узлы XML новыми узлами.

Скажите, что у меня есть следующая существующая структура XML:

<root>
    <criteria>
        <criterion>AAA</criterion>
    </criteria>
</root>

И я хочу заменить один узел критерия:

<criterion>BBB</criterion>
<criterion>CCC</criterion>
<criterion>DDD</criterion>

Так, чтобы заключительный результат XML был:

<root>
    <criteria>
        <criterion>BBB</criterion>
        <criterion>CCC</criterion>
        <criterion>DDD</criterion>
    </criteria>
</root>

Я попытался использовать подстроку - прежде и подстроку - после, чтобы просто скопировать первую половину структуры, затем просто скопируйте вторую половину (для заполнения моих новых узлов, промежуточных эти две половины), но кажется, что функции подстроки только распознают текст, промежуточный теги узлов, а не сами теги как я хочу их к. :( :(

Какие-либо другие решения?

9
задан John Saunders 1 June 2010 в 19:18
поделиться

3 ответа

XSL не может заменить что-либо. Лучшее, что вы можете сделать, это скопировать части, которые вы хотите сохранить, а затем вывести части, которые вы хотите изменить, вместо частей, которые вы не хотите сохранять.


Пример:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

    <!-- This is an identity template - it copies everything
         that doesn't match another template -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

  <!-- This is the "other template". It says to use your BBB-DDD elements
       instead of the AAA element -->
  <xsl:template match="criterion[.='AAA']">
    <xsl:element name="criterion">
      <xsl:text>BBB</xsl:text>
    </xsl:element>
    <xsl:element name="criterion">
      <xsl:text>CCC</xsl:text>
    </xsl:element>
    <xsl:element name="criterion">
      <xsl:text>DDD</xsl:text>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Шаблонное соответствие @* | node() соответствует любому атрибуту или любому другому типу узла. Хитрость заключается в том, что шаблонные соответствия имеют приоритеты. Вы можете считать, что правило звучит так: "побеждает более конкретное соответствие". Anything будет более конкретным, чем "любой атрибут или другой узел". Это делает соответствие "идентичность" очень низкоприоритетным.

Когда совпадает, он просто копирует любые узлы, которые он находит внутри совпадающего атрибута или узла.

Любые другие шаблоны, которые у вас есть, будут иметь более высокий приоритет. Что бы они ни совпадали, эффект будет иметь код внутри более конкретного шаблона. Например, если вы просто удалите все внутри шаблона criterion[.='AAA'], то обнаружите, что вы точно скопировали свой ввод, за исключением элемента "AAA".

24
ответ дан 4 December 2019 в 07:13
поделиться

Согласно общему правилу более чем один путь-скин-кота

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <xsl:apply-templates />
    </xsl:template>
    <!--  
        when you capture a node with the text 'AAA'
            emit the BBB, CCC, DDD nodes
     -->
    <xsl:template match="criterion[text() = 'AAA']">
        <xsl:element name="criterion">
            <xsl:text>BBB</xsl:text>
        </xsl:element>
        <xsl:element name="criterion">
            <xsl:text>CCC</xsl:text>
        </xsl:element>
        <xsl:element name="criterion">
            <xsl:text>DDD</xsl:text>
        </xsl:element>
    </xsl:template>
    <!--  identity template  -->
    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
0
ответ дан 4 December 2019 в 07:13
поделиться

Вот одно правильное решение, которое, вероятно, является одним из самых коротких :

 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="criterion[. = 'AAA']">
  <criterion>BBB</criterion>
  <criterion>CCC</criterion>
  <criterion>DDD</criterion> </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному XML-документу, получается желаемый результат :

<root>
    <criteria>
        <criterion>BBB</criterion>
        <criterion>CCC</criterion>
        <criterion>DDD</criterion>
    </criteria>
</root>

Обратите внимание на :

  1. Использование шаблона идентификации .

  2. Как шаблон идентификации заменяется определенным шаблоном - только для элемента критерия , строковое значение которого равно 'AAA' .

7
ответ дан 4 December 2019 в 07:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: