В этом 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 Я добавил таблицу стилей, которую я сделал в вопросе. Я новичок в xslt, у меня был опыт использования xsl:fo для преобразования xmls в pdf, но не xml в xml, и я тоже новичок в XPath!
Дизайн преобразования должен начинаться с преобразования удостоверений (см. раздел «Пример: преобразование удостоверений» в 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+.
Учитывая, что в вопросе явно упоминается XSLT 2, и мне все равно пришлось использовать xpath-default-namespace = "http://www.example.com/something"
, я не понимаю, почему обратная совместимость имеет значение.
Извините, но xpath-default-namespace
это тоже не нужно. Я хочу подчеркнуть, что перезапись правила идентичности является базовой схемой преобразования, поэтому новая инструкция xsl:mode
была введена, как вы правильно ответили.
@MartinHonnen Можете ли вы сказать мне, как изменить пространства имен из корня. В посте я дал только одно, но в моем xml у меня более 5 пространств имен, а также xsl: schemaLocation.
@BhavaniChandra, вам нужно будет задать новый отдельный вопрос, в котором вы предоставите минимальные, но полные сведения о входных данных XML, которые у вас есть, и о желаемом результате преобразования вместе с имеющимся у вас кодом, чтобы продемонстрировать, какая у вас проблема.
Почему бы вам не опубликовать свою попытку, чтобы мы могли ее исправить, вместо того, чтобы писать код для вас с нуля.