Search code examples
xsltxpathtemplate-matching

Merging pairs of nodes based on attribute, new to template matching


Say I have the following XML:

<root>
   <tokens>
      <token ID="t1">blah</token>
      <token ID="t2">blabla</token>
      <token ID="t3">shovel</token>
   </tokens>

   <relatedStuff>
      <group gID="s1">
        <references tokID="t1"/>
        <references tokID="t2"/>
      </group>

      <group gID="s2">
        <references tokID="t3"/>
      </group>

   </relatedStuff>
</root>

Now, considering that a for-each loop for every token would be pretty inefficient and a bad idea, how would one go about using template matching, to transform this xml into the following?

<s id="everything_merged"> 
    <tok id="t1" gID="s1" >blah</tok> 
    <tok id="t2" gID="s1" >blabla</tok> 

    <tok id="t3" gID="s2" >shovel</tok>
</s> 

All I want from <s> is the "gID", the gID corresponding to the token in the <tokens>.

<xsl:for-each select="b:root/a:tokens/a:token">
    <!-- and here some template matching -->
    <xsl:attribute name="gID">
         <xsl:value-of select="--correspondingNode's--@gID"/>
    </xsl:attribute>

</xsl:for-each>

I'm pretty fuzzy on this sort of thing, so thank you very much for any help!


Solution

  • The following stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/">
            <s id="everything_merged">
                <xsl:apply-templates select="/root/tokens/token" />
            </s>
        </xsl:template>
        <xsl:template match="token">
            <tok id="{@ID}" gID="{/root/relatedStuff/group[
                                    references[@tokID=current()/@ID]]/@gID}">
                <xsl:apply-templates />
            </tok>
        </xsl:template>
    </xsl:stylesheet>
    

    Applied to this input (corrected for well-formedness):

    <root>
        <tokens>
            <token ID="t1">blah</token>
            <token ID="t2">blabla</token>
            <token ID="t3">shovel</token>
        </tokens>
        <relatedStuff>
            <group gID="s1">
                <references tokID="t1" />
                <references tokID="t2" />
            </group>
            <group gID="s2">
                <references tokID="t3" />
            </group>
        </relatedStuff>
    </root>
    

    Produces:

    <s id="everything_merged">
        <tok id="t1" gID="s1">blah</tok>
        <tok id="t2" gID="s1">blabla</tok>
        <tok id="t3" gID="s2">shovel</tok>
    </s>