Ashok.N
Ashok.N

Reputation: 1391

Move XSLT tags from one place to another using their position

I am new to XSLT. Below is the input XML:

<?xml version="1.0" encoding="UTF-8"?>
<response>
   <results>
      <Final-Results>
         <cases>
            <row>
               <CRDATTIM>2014-03-26-05.22.22.339840</CRDATTIM>
               <RECORDCD>C</RECORDCD>
            </row>
            <row>
               <CRDATTIM>2014-03-26-05.05.51.531840</CRDATTIM>
               <RECORDCD>C</RECORDCD>
            </row>
         </cases>
         <ResultantIssues>
            <issues>
               <row>
                  <IKEY>2014-03-26-05.22.22.193840T01</IKEY>
                  <PRTY>999</PRTY>
               </row>
            </issues>
            <issues>
               <row>
                  <IKEY>2014-03-26-05.00.27.105840T01</IKEY>
                  <PRTY>999</PRTY>
               </row>
               <row>
                  <IKEY>2014-03-26-05.00.27.751840T01</IKEY>
                  <PRTY>999</PRTY>
               </row>
            </issues>
         </ResultantIssues>
      </Final-Results>
   </results>
</response>

The above xml should be modified as below using XSLT.

<?xml version="1.0" encoding="UTF-8"?>
<response>
   <results>
      <Final-Results>
         <cases>
            <row>
               <CRDATTIM>2014-03-26-05.22.22.339840</CRDATTIM>
               <RECORDCD>C</RECORDCD>
               <issues>
                  <row>
                     <IKEY>2014-03-26-05.22.22.193840T01</IKEY>
                     <PRTY>999</PRTY>
                  </row>
               </issues>
            </row>
            <row>
               <CRDATTIM>2014-03-26-05.05.51.531840</CRDATTIM>
               <RECORDCD>C</RECORDCD>
               <issues>
                  <row>
                     <IKEY>2014-03-26-05.00.27.105840T01</IKEY>
                     <PRTY>999</PRTY>
                  </row>
                  <row>
                     <IKEY>2014-03-26-05.00.27.751840T01</IKEY>
                     <PRTY>999</PRTY>
                  </row>
               </issues>
            </row>
         </cases>
      </Final-Results>
   </results>
</response>

The idea is to move the content between the first <issues> </issues> tags to the first <row> </row> of <case> </case> tags and the second <issues> </issues> tags to the second <row> </row> of <case> </case> tags and so on. Here the number of <row> tags under<case> tags and the <issues> tags are uncertain.

I have tried with the solution given to the question after making minor modifications Using for loop in XSLT. But it is not working. I have used the following XSLT code:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <response>
        <cases>
            <xsl:apply-templates select="response/results/Final-Results/cases"/>
        </cases>
    </response>
</xsl:template>
<xsl:template match="response/results/Final-Results/cases">
    <xsl:variable name="pos" select="position()"/>
    <xsl:copy>
        <xsl:value-of select="."/>
        <xsl:copy-of select="//response/results/Final-Results/ResultantIssues[position() = $pos]/issues"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

I am unable to figure out whats wrong with my code. Of course, my code is not producing the desired output for sure. Can anybody help me on this issue by providing an answer?

Please feel free to add a comment if my question is not clear so that I can put it in better words. Thanks in advance.

Upvotes: 1

Views: 1298

Answers (1)

Linga Murthy C S
Linga Murthy C S

Reputation: 5432

Hope this helps:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="cases/row">
    <xsl:variable name="pos" select="position()"/>
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:copy-of select="*"/>
        <xsl:copy-of select="../../ResultantIssues/issues[position() = $pos]"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="Final-Results">
    <xsl:copy>
        <xsl:apply-templates select="cases"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
  1. The first template(matches="node() | @*") is used to copy attributes(when applied to attributes), and to copy element tags and apply templates to the element's child nodes.
  2. The third template(matches="Final-Results"), when applied, copies "Final-Results" tag and apply templates to its "cases" child elements, thus avoiding any action on "ResultantIssues".
  3. The second template, matches="cases/row", stores the position() of the "cases/row" in a variable, create row tags, copy every child element and attributes in current "row" tag using:

    <xsl:apply-templates select="@*"/>
    <xsl:copy-of select="*"/>
    

    and using

    <xsl:copy-of select="../../ResultantIssues/issues[position() = $pos]"/>
    

    moves to ResultantIssues, picks the "issues" with current position, and copies it into "row". I'm bad at explaining.

Upvotes: 2

Related Questions