Мне нужно решение 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>
Я попытался использовать подстроку - прежде и подстроку - после, чтобы просто скопировать первую половину структуры, затем просто скопируйте вторую половину (для заполнения моих новых узлов, промежуточных эти две половины), но кажется, что функции подстроки только распознают текст, промежуточный теги узлов, а не сами теги как я хочу их к. :( :(
Какие-либо другие решения?
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".
Согласно общему правилу более чем один путь-скин-кота
<?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>
Вот одно правильное решение, которое, вероятно, является одним из самых коротких :
<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>
Обратите внимание на :
Использование шаблона идентификации .
Как шаблон идентификации заменяется определенным шаблоном - только для элемента критерия
, строковое значение которого равно 'AAA'
.