Search code examples
xmlxsltxslt-grouping

XSLT - Refer HREF elements


I have a XML in the below format

<Envelope>
<Body>
<Ref id="ref1">
<user>Test1</user>
<company>Comp1</company>
<message href="#ref3" />
</Ref>
<Ref id="ref2">
<user>Test2</user>
<company>Comp2</company>
<message href="#ref4" />
</Ref>
<Ref id="ref3">Test message 1</Ref>
<Ref id ="ref4">Test message 2</Ref>
</Body>
</Envelope>

Using XLST I want to transform the above XML as below .I am totally new to XSLT, Can anyone please help me with this

Expected Output:

<Envelope>
<Body>
<Ref>
<user>Test1</user>
<company>Comp1</company>
<message>Test message 1</message>
</Ref>
<Ref>
<user>Test2</user>
<company>Comp2</company>
<message>Test message 1</message>
</Ref>
</Body>
</Envelope>

Solution

  • I would create an xsl:key for the Ref elements, using the @id as the lookup key.

    A template for the message/@href that uses it's value as the key to lookup a message, and another empty template for the Ref elements that only have messages to suppress them from output.

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0">
        <xsl:output method="xml" version="1.0" indent="yes"/>
        
        <xsl:key name="message" match="Ref" use="@id"/>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        
        <xsl:template match="message/@href">
            <xsl:value-of select="key('message', substring-after(., '#'))"/>
        </xsl:template>
        
        <xsl:template match="Ref[not(*)]"/>
        
    </xsl:stylesheet>