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???

Recommended Answers

All 5 Replies

Is it safe to assume that every <name> node will have a corresponding <duration> and <time> node?

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>

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

Have just tested, at present it will not work.

Looking for a solution to the issue it causes.

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>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.