Вот полностью общее и короткое решение XSLT 1.0. Он использует отображение XML-файл, который указывает на замену для каждого хотел выпустить: (. Пожалуйста, найдите в конце этого ответа на конечном счете, родовое и короткое решение, написанное в XSLT 2.0)
<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:variable name="vMap" select="document('mapping.xml')/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="release[. = document('mapping.xml')/*/release/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
</xsl:stylesheet>
Если файл mapping.xml
находится в том же каталоге, что и преобразования (файл .xsl), и:
<map>
<release old="A">
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</release>
<release old="B">
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</release>
</map>
тогда, когда т он преобразование применяется на этот XML-документ:
<root>
<cr>
<id>1</id>
<release>A</release>
</cr>
<cr>
<id>2</id>
<release>B</release>
</cr>
<cr>
<id>3</id>
<release>C</release>
</cr>
<cr>
<id>4</id>
<release>D</release>
</cr>
</root>
разыскиваемый, правильный результат получается:
<root>
<cr>
<id>1</id>
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</cr>
<cr>
<id>2</id>
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</cr>
<cr>
<id>3</id>
<release>C</release>
</cr>
<cr>
<id>4</id>
<release>D</release>
</cr>
</root>
Примечание: Многие, иначе названные элементы могут быть заменены такое же преобразование.
Если у нас есть этот файл отображения:
<map>
<release old="A">
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</release>
<release old="B">
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</release>
<history old="p">
<history>Pp</history>
<history>Pq</history>
<history>Pr</history>
</history>
</map>
и этот исходный XML-документ:
<root>
<cr>
<id>1</id>
<history>p</history>
<release>A</release>
</cr>
<cr>
<id>2</id>
<history>q</history>
<release>B</release>
</cr>
<cr>
<id>3</id>
<history>r</history>
<release>C</release>
</cr>
<cr>
<id>4</id>
<history>t</history>
<release>D</release>
</cr>
</root>
то это преобразование:
<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:variable name="vMap" select="document('mapping.xml')/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="release[. = document('mapping.xml')/*/release/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
<xsl:template match="history[. = document('mapping.xml')/*/history/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
</xsl:stylesheet>
при нанесении на вышеуказанном документе XML, производит желаемый результат - где больше, чем один-другому названные элементы отображенных и заменить:
<root>
<cr>
<id>1</id>
<history>Pp</history>
<history>Pq</history>
<history>Pr</history>
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</cr>
<cr>
<id>2</id>
<history>q</history>
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</cr>
<cr>
<id>3</id>
<history>r</history>
<release>C</release>
</cr>
<cr>
<id>4</id>
<history>t</history>
<release>D</release>
</cr>
</root>
Наконец: еще короче и более общими преобразование можно записать в XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vMap" select="document('mapping.xml')/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[. = $vMap[name() eq name(current())]/@old]">
<xsl:copy-of select="$vMap[name() eq name(current()) and @old eq current()]/*"/>
</xsl:template>
</xsl:stylesheet>
Обратите внимание: нет имя элемента не зашито в этом преобразовании!
Еще большее преимущество: Мы можем изменить преобразование, чтобы мы могли передавать URI документа отображения в качестве глобального параметра при вызове преобразования - таким образом, мы можем иметь одно общее генерирующее преобразование, которое работает с любым , неизвестное заранее отображение.
только эти необходимые изменения:
<xsl:param name="pmapUrl" select="'file:///c:/temp/mapping.xml'"/>
<xsl:variable name="vMap" select="document($pmapUrl)/*/*"/>
Полное преобразование (глобальный параметр pmapUrl
может и обычно будет указано динамически вызвавшего трансформации):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pmapUrl" select="'file:///c:/temp/mapping.xml'"/>
<xsl:variable name="vMap" select="document($pmapUrl)/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[for $name in name()
return
. = $vMap[name() eq $name]/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
</xsl:stylesheet>
Можете ли вы показать вам текущую попытку, пожалуйста? Кроме того, можете ли вы уточнить, как именно много элементов вы хотите показать. Например, для «B» вы говорите, что хотите «Bd» и «Be» и т. Д., Но почему бы не «Bc»? Вы хотите пройти весь путь до «Bz»? Спасибо? –
Является ли число повторений фиксированным и известным при написании XSLT? В этом случае вы можете использовать три режима для трех повторений и три 'apply-templates' для трех повторений. Я еще не понял, что определяет ценности новых элементов. –
Спасибо, отредактировал его. – dellair