Hi,

I have a requirement in XSLT where in I have a xml as below,

<Process>
    <name></name>
    <duration></duration>
    <time></time>
    <name></name>
    <duration></duration>
    <time></time>
    <name></name>
    <duration></duration>
    <time></time>
    .
    .
    .
    .
</Process>


<The first <name> node we get we create a Process_INfo and copy <name> in it and all other node following <name> till we get other <name> node. AS soon as we get a new <name> node we create a new <Process_Info> node amd repeat the previous process till we are done with all <name> nodes

I have to tranfrom this xsml using XSLT as,

<Process>
    <Process_Info>
        <name></name>
        <duration></duration>
        <time></time>
    </Process_Info>
    <Process_Info>
        <name></name>
        <duration></duration>
        <time></time>
    </Process_Info>
    ..
    ..
    ..
    ..        
</Process>


Can you please let me know how we can do this???

The XSLT works by storing all the XML within <Process> root node allowing access to it within the <name> for-each selects.

Within each for-each we get the position() of the <name> and then copy in the <time> and <duration> with the same positions.

XSLT

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:variable name ="varProcess" select ="Process"/>

  <xsl:template match="Process">
    <xsl:element name="Process">
      <xsl:for-each select ="name">
        <xsl:variable name ="varPosition" select ="position()"/>
        <xsl:element name ="Process_Info">
          <xsl:copy-of select ="."/>
          <xsl:copy-of select="$varProcess/duration[$varPosition]"/>
          <xsl:copy-of select="$varProcess/time[$varPosition]"/>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

INPUT

<Process>
  <name>Pro1</name>
  <duration>Dur1</duration>
  <time>Time1</time>
  <name>Pro2</name>
  <duration>Dur2</duration>
  <time>Time2</time>
  <name>Pro3</name>
  <duration>Dur3</duration>
  <time>Time3</time>
  <name>Pro4</name>
  <duration>Dur4</duration>
  <time>Time4</time>
  <name>Pro5</name>
  <duration>Dur5</duration>
  <time>Time5</time>
</Process>

OUTPUT

<Process>
  <Process_Info>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
  </Process_Info>
  <Process_Info>
    <name>Pro2</name>
    <duration>Dur2</duration>
    <time>Time2</time>
  </Process_Info>
  <Process_Info>
    <name>Pro3</name>
    <duration>Dur3</duration>
    <time>Time3</time>
  </Process_Info>
  <Process_Info>
    <name>Pro4</name>
    <duration>Dur4</duration>
    <time>Time4</time>
  </Process_Info>
  <Process_Info>
    <name>Pro5</name>
    <duration>Dur5</duration>
    <time>Time5</time>
  </Process_Info>
</Process>

Edited 4 Years Ago by Mike Askew

Hi Mike,

   The <name> node will be there for sure. But the other two nodes are optional. Tey may come or may not come. will the solution work in this case?

Thanks

The below XSLT works regardless of node occurance.

Credit to nonnb on StackOverflow.
Route to solution if interested: http://stackoverflow.com/questions/11537036/xslt-select-specific-nodes-below-current

XSLT

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="Process">
    <xsl:element name="Process">
      <xsl:for-each select ="name">
        <xsl:element name ="Process_Info">
          <xsl:copy-of select ="."/>
          <xsl:variable name="firstSib" select="local-name(following-sibling::*[1])" />
          <xsl:variable name="secondSib" select="local-name(following-sibling::*[2])" />
          <xsl:if test ="($firstSib='duration') or ($firstSib='time')">
            <xsl:copy-of select="following-sibling::*[1]"/>
          </xsl:if>
          <xsl:if test ="($secondSib='duration') or ($secondSib='time')">
            <xsl:copy-of select="following-sibling::*[2]"/>
          </xsl:if>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Edited 4 Years Ago by Mike Askew

This article has been dead for over six months. Start a new discussion instead.