Я думаю, что это может быть хорошим примером использования функции snapshot
XSLT 3 вместе со вторым режимом и параметром туннеля для передачи этого LineItemPrice
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:mode name="price" on-no-match="shallow-copy"/>
<xsl:template match="LineItem">
<xsl:apply-templates select=".//Product!snapshot()/ancestor::LineItem" mode="price">
<xsl:with-param name="price" tunnel="yes" select="LineItemPrice"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="LineItem" mode="price">
<xsl:param name="price" tunnel="yes"/>
<xsl:copy>
<xsl:apply-templates select="@*, $price, node()" mode="#current"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty -development.net / bFN1y8J
XSLT 3 доступен с Saxon 9.8 или более поздней версии или Altova 2017 и более поздней версии, поэтому есть вероятность, что если вы используете современный процессор XSLT 2, у вас есть процессор, который также может использовать XSLT 3 вместо тегов XSLT 2.
XSLT 2 не имеет snapshot
, но, конечно, вы можете попытаться реализовать один и тот же подход, заключающийся в том, чтобы продвигать каждый продукт в отдельном режиме, чтобы также реконструировать поддерево, только теперь другие шаблоны должны исключать все, кроме один Product
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="2.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@* | node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="LineItem">
<xsl:apply-templates select=".//Product"/>
</xsl:template>
<xsl:template match="Product">
<xsl:apply-templates select="ancestor::LineItem" mode="price">
<xsl:with-param name="product" tunnel="yes" select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Product" mode="price">
<xsl:param name="product" tunnel="yes"/>
<xsl:if test=". is $product">
<xsl:next-match/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty -development.net / bFN1y8J / 1