Замените узлы xml с помощью xslt

В этом xml я хочу заменить узел <transfom> другим узлом <message>, но скопировать данные.

Возможно ли это с помощью xslt? Я использовал xslt 2.0, чтобы преобразовать узел преобразования в узел сообщения, но он работает только для одного узла потока.

<root
    xmlns = "http://www.example.com/something">
    <flow>
        <list name = "listName"/>
        <router name = "router"/>
        <!-- I have some other tags here -->
    </flow>
    <flow>
        <list name = "listName"/>
        <console name = "console"/>
        <!-- I have some other tags here -->
    </flow>
    <flow>
        <payload name = "example"/>
        <transform name = "transform">
            <!-- Some DATA here --->
        </transform>
        <!-- I have some other tags here -->
    </flow>
    <flow>
        <payload name = "sada"/>
        <transform name = "transform1">
            <!-- Some DATA here --->
        </transform>
        <!-- I have some other tags here -->
        <transform name = "transform2">
            <!-- Some DATA here --->
        </transform>
    </flow>
</root>

Узлы <transform> присутствуют в двух узлах <flow>. Есть ли способ написать общий XSLT, чтобы заменить узел <transform> на узел <message>, сохраняя положение узлов и данные внутри узлов.

Я использовал <xsl:for-each> и <xsl:when> и выражения xpath, такие как предыдущий, следующий. Но они конвертируют только <transform name = "transform node">, а все остальные узлы xml копируют как есть. Пожалуйста, дайте мне знать, как решить эту проблему!


Обновлять

Это таблица стилей, которую я использовал для преобразования xml

<xsl:stylesheet version = "2.0"
    xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
    <root>
        <xsl:for-each select = "flow">
            <xsl:choose>
                <xsl:when test = "descendant-or-self::transform">
                    <message>
                        <xsl:attribute name = "doc:name">
                            <xsl:value-of
                                        select = "//transform/@name" />
                        </xsl:attribute>
                        <ee:message>
                            <ee:set-payload>
                                <xsl:value-of select = "payload" />
                            </ee:set-payload>
                        </ee:message>
                    </ee:transform>
                </xsl:when>
            </xsl:choose>
        </xsl:for-each>
    </root>
</xsl:stylesheet>

Обновление 14.04.2019

Как изменить пространства имен из тега <root>? У меня есть куча пространств имен, которые нужно изменить при преобразовании. Как это сделать?

Почему бы вам не опубликовать свою попытку, чтобы мы могли ее исправить, вместо того, чтобы писать код для вас с нуля.

michael.hor257k 07.04.2019 13:26

@ michael.hor257k Я добавил таблицу стилей, которую я сделал в вопросе. Я новичок в xslt, у меня был опыт использования xsl:fo для преобразования xmls в pdf, но не xml в xml, и я тоже новичок в XPath!

Bhavani Chandra 07.04.2019 14:03
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
482
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Дизайн преобразования должен начинаться с преобразования удостоверений (см. раздел «Пример: преобразование удостоверений» в https://www.w3.org/TR/xslt20/#элемент-копия), а затем добавлять только шаблоны для узлов, которые вы хотите преобразовать, в XSLT 3 вы можете объявить преобразование удостоверений как обработку по умолчанию, используя <xsl:mode on-no-match = "shallow-copy"/> (https://www.w3.org/TR/xslt-30/#built-in-templates-shallow-copy), а затем вам просто нужно написать шаблон для элементов transform:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
    xmlns:xs = "http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace = "http://www.example.com/something"
    xmlns = "http://www.example.com/something"
    exclude-result-prefixes = "#all"
    version = "3.0">

  <xsl:mode on-no-match = "shallow-copy"/>

  <xsl:template match = "flow/transform">
      <message>
          <xsl:apply-templates select = "@*, node()"/>
      </message>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/pPzifpw

в XSLT 2 вы должны указать это:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
    xmlns:xs = "http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace = "http://www.example.com/something"
    xmlns = "http://www.example.com/something"
    exclude-result-prefixes = "#all"
    version = "2.0">

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

  <xsl:template match = "flow/transform">
      <message>
          <xsl:apply-templates select = "@*, node()"/>
      </message>
  </xsl:template>

</xsl:stylesheet>

Извините, но я не вижу преимуществ от использования последовательности вместо набора узлов, кроме преобразования таблицы стилей, полностью совместимой с предыдущими версиями, в таблицу стилей только XSLT 2.0+.

Alejandro 08.04.2019 21:57

Учитывая, что в вопросе явно упоминается XSLT 2, и мне все равно пришлось использовать xpath-default-namespace = "http://www.example.com/something", я не понимаю, почему обратная совместимость имеет значение.

Martin Honnen 08.04.2019 22:15

Извините, но xpath-default-namespace это тоже не нужно. Я хочу подчеркнуть, что перезапись правила идентичности является базовой схемой преобразования, поэтому новая инструкция xsl:mode была введена, как вы правильно ответили.

Alejandro 08.04.2019 22:24

@MartinHonnen Можете ли вы сказать мне, как изменить пространства имен из корня. В посте я дал только одно, но в моем xml у меня более 5 пространств имен, а также xsl: schemaLocation.

Bhavani Chandra 14.04.2019 17:41

@BhavaniChandra, вам нужно будет задать новый отдельный вопрос, в котором вы предоставите минимальные, но полные сведения о входных данных XML, которые у вас есть, и о желаемом результате преобразования вместе с имеющимся у вас кодом, чтобы продемонстрировать, какая у вас проблема.

Martin Honnen 14.04.2019 17:48

Другие вопросы по теме