Вы можете использовать эту таблицу стилей XSLT-1.0:
<?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" indent="yes"/>
<xsl:template match="A" >
<X id="{@id}" name="{@name}">
<xsl:apply-templates select="B/d" />
</X>
</xsl:template>
<xsl:template match="d" >
<Y id="{@id}" name="{@name}">
<xsl:copy-of select="f" />
<xsl:apply-templates select="e" />
</Y>
</xsl:template>
<xsl:template match="e" >
<content>
<xsl:copy-of select="/A/C/e[current()/@ref = @id]/@* | /A/C/e[current()/@ref = @id]/*" />
</content>
</xsl:template>
</xsl:stylesheet>
Его вывод
<?xml version="1.0"?>
<X id="123" name="a">
<Y id="p123" name="one">
<f>Hello</f>
<content id="c123" type="paragraph">
<text>Dummy Text</text>
</content>
</Y>
<Y id="p234" name="two">
<f>Hello</f>
<content id="c234" type="link" url="google.com"/>
<content id="c123" type="paragraph">
<text>Dummy Text</text>
</content>
</Y>
</X>
Первый тип <content>
не является "TEXT", потому что это будет были нерегулярными. Я предположил, что вам нужен обычный вывод.
Если скорость критична, вы можете реализовать оптимизацию, предложенную в комментариях:
Добавить xsl:key
на верхнем уровне:
<xsl:key name="ids" match="/A/C/e" use="@id" />
И доступ к нему в шаблоне e
<xsl:copy-of select="key('ids',current()/@ref)/@* | key('ids',current()/@ref)/@*" />
Это все еще выполняет поиск дважды. Если вас это беспокоит, вы можете кэшировать результат xsl:key
в переменной.