XSLT принимает XML-документ в качестве дерева ввода и затем генерирует вывод.Когда вывод также является XML, он эффективно преобразует дерево ввода в дерево вывода.Это означает, что вам не остается места для изменения дерева ввода во время чтения.Насколько я знаю, вы также не можете передавать частичные результаты в качестве входных данных для шаблонов.Поэтому я предлагаю выполнить два преобразования XSLT подряд.Один для преобразования ввода в желаемый виртуальный промежуточный результат, другой для выполнения фактической обработки, которая потребуется для этого формата, когда унаследованные структуры свернуты в плоские.
XSLT для этого первого шага может использовать этов качестве основы:
<?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" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>
</xsl:template>
<xsl:template match="//*[@base]">
<xsl:variable name="base" select="@base"/>
<xsl:copy><xsl:copy-of select="./node() | ./@*[local-name() != 'base'] | //*[@name=$base]/@*"></xsl:copy-of><xsl:copy-of select="//*[@name=$base]/node()"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
Это преобразовало бы следующее ...
<?xml version="1.0" encoding="UTF-8"?>
<root>
<test name="one" hello="kitty">
<one hello="world">test</one>
<two/>
</test>
<bogus att="none">
<test/>
</bogus>
<test base="one" run="true" hello="kitty">
<three/>
</test>
</root>
... в это:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<test name="one" hello="kitty">
<one hello="world">test</one>
<two/>
</test>
<bogus att="none">
<test/>
</bogus>
<test name="one" run="true" hello="kitty">
<three/>
<one hello="world">test</one>
<two/>
</test>
</root>
Есть некоторые крайние случаи дляразрабатывать.Если и элемент с атрибутом name
, и элемент с атрибутом base
имеют атрибуты с одинаковым именем, процессор обнаружит это и сохранит только один.Это случай с hello="kitty"
здесь.Но если эти атрибуты имеют разные значения, результат трудно предсказать.Вы также можете подавить начальный элемент подшипника name
.Для этого просто добавьте шаблон, который ничего не выводит для элементов с атрибутом name
.
После этого преобразования вы можете применить второй.Я предположил, что ваше "наследование" вложено только в одну глубину, и только одно имя появляется на базе.Если это не так, эта стратегия может не сработать.Я оставлю вас для обработки деталей.