简体   繁体   中英

XSL: How can I replace a node value in an XML with the value of a child of another node while matching on another child node?

I am trying to match two XML nodes then replace the first node value with the value of a sibling node value of the second. In terms of XML:

Input XML

 <root> <Base> <unit> <Target>4</Target> <Other></Other> </unit> <unit> <Target>17</Target> <Other></Other> </unit> <unit> <Target>4</Target> <Other></Other> </unit> </Base> <Addition> <center> <Key>4</Key> <value>501033</value> </center> <center> <Key>17</Key> <value>101012</value> </center> <center> <Key>7</Key> <value>123232</value> </center> </Addition> </root>

Desired Output XML

 <root> <Base> <unit> <Target>501033</Target> <Other></Other> </unit> <unit> <Target>101012</Target> <Other></Other> </unit> <unit> <Target>501033</Target> <Other></Other> </unit> </Base> </root>

So, I would like to replace the 'Target' node's value in 'Base' with the value of the 'value' node in 'Addition' if Target in 'Base' equals the 'Key' in 'Addition'.

How can this be achieved with XSL / XSLT in the most efficient manner?

My current code looks like this:

 <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <:--copies the base xml --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <:-- replaces the cost center code --> <xsl.for-each select="Base/Target"> <xsl:variable name="TargetKey" select = ":"></xsl:variable> <xsl:template match="Addition/Key"> <xsl:copy> <xsl:value-of select="Addition[Key=$TargetKey]"/> </xsl:copy> </xsl:template> </xsl:for-each> </xsl:stylesheet>

I would use an xsl:key for the Addition/center elements, lookup by the Key with the Target value, and then retrieve it's value , and add an empty template for Addition in order to exclude those from the output:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:key name="center-by-Key" match="Addition/center" use="Key" />
    
    <!--copies the base xml --> 
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="Addition"/>
    
    <!-- replaces the cost center code --> 
    <xsl:template match="Target">
        <xsl:copy>
            <xsl:value-of select="key('center-by-Key', .)/value"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM