Search code examples
xslt-2.0

XSLT propagating Parent element into each child in a child list


Am new to XSLT and am just not able to wrap my head around this one. I have an XML as follows:

<root>
  <key>1</key>
  <list>
        <value>1</value>
        <value>2</value>
  </list>
</root>

What I want to achieve is this:

<root>
    <row>   
        <key>1</key>
         <value>1</value>
    </row>
    <row>   
        <key>1</key>
        <value>2</value>
   </row>         
</root>

Solution

  • Your requirements are not entirely clear, but let's give it a try:

    <xsl:template match="/root">
        <xsl:copy>
            <!-- each first following sibling after <key> -->
            <xsl:apply-templates select="key/following-sibling::list[1]" />
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="list">
        <xsl:apply-templates />
    </xsl:template>
    
    <xsl:template match="value">
        <row>
            <!-- the key immediately before the current <list> -->
            <xsl:copy-of select="ancestor::list/preceding-sibling::key[1]" />
            <xsl:copy-of select="." />
        </row>
    </xsl:template>
    

    This code assumes a basic understanding of XSLT. And it assumes my understanding that a list element is preceded directly by a key element and that each row/value becomes a row with a value and the preceding key.

    You tagged your question XSLT 2.0, but this code works with either XSLT 1.0 or 2.0 (and in this particular case will not be very different if you tried using the 2.0 features).

    Tested with a 1.0 (.NET) and two 2.0 (Exselt and Saxon) processors against the following modified input:

    <root>
      <key>1</key>
      <list>
            <value>1</value>
            <value>2</value>
      </list>
      <key>2</key>
      <list>
            <value>55</value>
            <value>66</value>
            <value>77</value>
      </list>
    </root>
    

    Resulting in the following output:

    <root>
       <row>
          <key>1</key>
          <value>1</value>
       </row>
       <row>
          <key>1</key>
          <value>2</value>
       </row>
       <row>
          <key>2</key>
          <value>55</value>
       </row>
       <row>
          <key>2</key>
          <value>66</value>
       </row>
       <row>
          <key>2</key>
          <value>77</value>
       </row>
    </root>