Saturday, June 2, 2012

XML page using XSLT - one table page with different flavours

For some time now I am working on building a generic XSL which can be used to format different XML as per the defined standard. In this posting will be showing you the basic logic of building the XML and XSL. This has been created manually; will be working further to automate the XML generation as well as XSL generation.

Following screenshots of the webpage that has been generated and following objectives has been achieved in implementation.
  1. One standard XSL for generating formatting multiple XML. 
  2. Display all data in a single page in different ways. 
  3. XML should contain instructions of how data should get displayed and not XSL. 
Page when loaded:












Page when expanded:

Implementation:
I am not describing how it has been implemented but use both the XML and XSL to generate your page. Get your hands dirty and understand it and try to implement it the way you want. Basic things in implementation one Tag bifurcated by Type; how to display data depends upon Type (List/ Record/ Field)

Sample XML
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="TEST_XSL.xsl"?>
<Node Desc="XXX Screen" Type="ReplyScreen">
  <Node Type="List" Desc="General Header" DisplayINList="NO">
    <Node Type="Record" Desc="" BOLD="YES">
      <Node Type="Field">
        <Label1>Name</Label1>
        <Data1>Test Name</Data1>
        <Label2>Status</Label2>
        <Data2>Test Status</Data2>
      </Node>
      <Node Type="Field">
        <Label1>Code</Label1>
        <Data1>XYZ</Data1>
        <Label2>Number</Label2>
        <Data2>*********901</Data2>
      </Node>
    </Node>
  </Node>
  <Node Type="List" Desc="" DisplayINList="YES">
    <Node Type="Record" Desc="Other Details" BOLD="YES">
      <Node Type="Field">
        <Label1>Address Line 1</Label1>
        <Data1>1234 XXXX</Data1>
        <Label2>Address Line 2</Label2>
        <Data2>7890 YYYY</Data2>
      </Node>
      <Node Type="Field">
        <Label1>Name 1</Label1>
        <Data1>TEST NAME 1</Data1>
        <Label2>Name 2</Label2>
        <Data2>TEST NAME 2</Data2>
      </Node>
    </Node>
  </Node>
  <Node Type="List" Desc="XXX Details" DisplayINList="YES">
    <Node Type="Record" Desc="55 - 000003002009 Amount 10.00" BOLD="YES">
      <Node Type="Field">
        <Label1>Code</Label1>
        <Data1>55</Data1>
        <Label2>Number</Label2>
        <Data2>*********009</Data2>
      </Node>
      <Node Type="Field">
        <Label1>Date</Label1>
        <Data1>07/14/03</Data1>
        <Label2>Expire Date</Label2>
        <Data2>99/99/99</Data2>
      </Node>
    </Node>
    <Node Type="Record" Desc="00 - 000000000001 Amount 100.00" BOLD="YES">
      <Node Type="Field">
        <Label1>B1</Label1>
        <Data1>XXX 1</Data1>
        <Label2>B2</Label2>
        <Data2>XXX 2</Data2>
      </Node>
      <Node Type="Field">
        <Label1>B</Label1>
        <Data1>100207</Data1>
        <Label2>Date</Label2>
        <Data2>99/99/99</Data2>
      </Node>
    </Node>
  </Node>
  <Node Type="List" Desc="Name Details" DisplayINList="NO">
    <Node Type="Record" Desc="" BOLD="YES">
      <Node Type="Field">
        <Label1>A1</Label1>
        <Data1>Description 1</Data1>
        <Label2>@#$%^</Label2>
        <Data2>@#$%^</Data2>
      </Node>
      <Node Type="Field">
        <Label1>A2</Label1>
        <Data1>Description 2</Data1>
        <Label2>@#$%^</Label2>
        <Data2>@#$%^</Data2>
      </Node>
    </Node>
  </Node>
  <Node Type="List" Desc="Other Messages" DisplayINList="NO">
    <Node Type="Record" Desc="Message 1" BOLD="NO" />
    <Node Type="Record" Desc="Message 2" BOLD="NO" />
  </Node>
</Node>

Sample XSL
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
    <head>
      <script language="JavaScript">
        <xsl:comment>
          <![CDATA[
 
         function GetElemParent(elem)
         {
          var ret = null;
          if(elem.level == 1)
           return ret;
          var prevSibling = elem.previousSibling;
          while(prevSibling)
          {
           if(parseInt(prevSibling.level) == (parseInt(elem.level) - 1))
           {
            ret = prevSibling;
            break;
           }
           prevSibling = prevSibling.previousSibling;
          }
          return ret;
         }
         
         function GetElemChildren(elem)
         {
          var ret = new Array();
          
          var index = 0;
          var nextSibling = elem.nextSibling;
          while(nextSibling)
          {
           if(parseInt(nextSibling.level) == (parseInt(elem.level) + 1))
           {
            ret[index] = nextSibling;
            index++;
           }
           else if(parseInt(nextSibling.level) == parseInt(elem.level))
            break;
           nextSibling = nextSibling.nextSibling;
          }
          return ret;
         }
         
         function ExpandElement(elem)
         {
          var children = GetElemChildren(elem);
          for(var i = 0; i < children.length; i++)
          {
           var child = children[i];
           ShowElement(child);
          }
         }
         
         function CollapseElement(elem)
         {
          var children = GetElemChildren(elem);
          for(var i = 0; i < children.length; i++)
          {
           var child = children[i];
           HideElement(child);
          }
         }
         
         function ShowElement(elem)
         {
          elem.style.display = "";
          if(IsElementExpanded(elem))
          {
           var children = GetElemChildren(elem);
           for(var i = 0; i < children.length; i++)
           {
            var child = children[i];
            ShowElement(child);
           }
          }
         }
         
         function IsElementExpanded(elem)
         {
          var expanded = elem.children(0).expanded;
          if(expanded == undefined)
           return true;
          return expanded;
         }
         
         function HideElement(elem)
         {
          elem.style.display = "none";
          var children = GetElemChildren(elem);
          for(var i = 0; i < children.length; i++)
          {
           var child = children[i];
           HideElement(child);
          }
         }
         
         function DoExpandClick(elem)
         {
          if(window.event.srcElement.tagName == "IMG")
          {
           if(elem.expanded)
           {
            var parent = elem.parentElement;
            CollapseElement(parent);
            
            elem.expanded = false;
            elem.rowSpan = "1";
            elem.getElementsByTagName("IMG")(0).src = "expand.gif";
           }
           else
           {
            var parent = elem.parentElement;
            ExpandElement(parent);
            
            elem.expanded = true;
            elem.rowSpan = elem.rowspancfg;
            elem.getElementsByTagName("IMG")(0).src = "collapse.gif";
           }
          }
         }
         function DoCollapseLoad(elem)
         {
          var children = elem.all;
          for(var i = 0; i < children.length; i++)
          {
           var child = children[i];
           if (child.nodeName == "IMG")
           {
            child.click();
           }
          }
         }
        ]]>//
        </xsl:comment>
      </script>
     <h2 align="center">
       <xsl:apply-templates select="//Node" mode="head"/>
     </h2>
    </head>
    <body style="background-color:#d0e4fe; font-family:'Arial';" onload="DoCollapseLoad(document.firstChild)">
      <table border="0" cellpadding="1" style="border: 1px solid green; border-collapse:collapse; border-separation=0px" cellspacing="0">
        <xsl:apply-templates select="//Node" mode="row"/>
      </table>
    </body>
  </html>
</xsl:template>

<xsl:template match="Node" mode="head">
  <xsl:if test ="@Type='ReplyScreen'">
    <xsl:value-of select="@Desc"/>
  </xsl:if>
</xsl:template>

<xsl:template match="Node" mode="row">
  <xsl:if test ="@Type='Record' and @Desc!=''">
    <tr level="1" style="border:1px solid green;">
      <xsl:apply-templates select="self::Node" mode="popcell"/>
    </tr>
  </xsl:if>
  <xsl:if test ="@Type='Field'">
    <tr level="2">
      <xsl:apply-templates select="self::Node" mode="popcell"/>
    </tr>
  </xsl:if>
  <xsl:if test ="@Type='List' and @Desc!=''">
    <tr level="1">
      <xsl:apply-templates select="self::Node" mode="popcell"/>
    </tr>
  </xsl:if>
</xsl:template>

<xsl:template match="Node" mode="popcell">
  <xsl:if test ="@Type='Record' and ../@DisplayINList='YES'">
    <td valign="top"  expanded="true" onclick="DoExpandClick(this)">
      <xsl:if test="count(@Desc)>0">
        <xsl:variable name="rowspancount" select="count(child::Node) + 1"/>
        <xsl:attribute name ="rowspan">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
        <xsl:attribute name="rowspancfg">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
      </xsl:if>
      <xsl:if test="count(@Desc)=0">
        <xsl:variable name="rowspancount" select="count(child::Node)"/>
        <xsl:attribute name ="rowspan">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
        <xsl:attribute name="rowspancfg">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
      </xsl:if>
      <img src="./collapse.gif"/>
    </td>
    <xsl:if test="count(@Desc)>0">
      <xsl:if test="@BOLD='YES'">
        <td width="100%" valign="top" style="font-weight: bold; font-size:11pt; border:1px solid green;" colspan="4" bgcolor="#BDBDBD">
          <xsl:value-of select="@Desc"/>
        </td>
      </xsl:if>
      <xsl:if test="@BOLD='NO'">
        <td width="100%" valign="top" colspan="4" bgcolor="#F2F2F2" style="font-size:11pt; border:1px dotted green;"><!--assuming that data will display--> 
          <xsl:value-of select="@Desc"/>
        </td>
      </xsl:if>
    </xsl:if>
  </xsl:if>
  <xsl:if test ="@Type='Record' and ../@DisplayINList='NO'">
    <td valign="top"  expanded="true">
      <xsl:if test="@Desc!=''">
        <xsl:variable name="rowspancount" select="count(child::Node) + 1"/>
        <xsl:attribute name ="rowspan">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
        <xsl:attribute name="rowspancfg">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
      </xsl:if>
      <xsl:if test="@Desc=''">
        <xsl:variable name="rowspancount" select="count(child::Node)"/>
        <xsl:attribute name ="rowspan">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
        <xsl:attribute name="rowspancfg">
          <xsl:value-of select="$rowspancount"/>
        </xsl:attribute>
      </xsl:if>
    </td>
    <xsl:if test="@Desc!=''">
      <xsl:if test="@BOLD='YES'">
        <td width="100%" valign="top" colspan="4" bgcolor="#BDBDBD" style="font-weight: bold; font-size:11pt; border:1px solid green;">
          <xsl:value-of select="@Desc"/>
        </td>
      </xsl:if>
      <xsl:if test="@BOLD='NO'">
        <td width="100%" valign="top" colspan="4" bgcolor="#F2F2F2" style="font-size:11pt; border:1px dotted green;">
          <xsl:value-of select="@Desc"/>
        </td>
      </xsl:if>
    </xsl:if>
  </xsl:if>
  <xsl:if test ="@Type='Field'">
    <xsl:if test ="Label1[.!=''] and Data1[.!=''] and Label2[.!=''] and Label2[.!='@#$%^'] and Data2[.!=''] and Data2[.!='@#$%^']">
 <xsl:if test ="../@Type='Record' and ../@Desc=''">
  <td></td>
 </xsl:if>
      
   <td width="25%" valign="top" bgcolor="#D8D8D8" style="font-weight: bold; font-size:11pt; border:1px solid green;">
        <xsl:value-of select="Label1"/>
      </td>
      <td width="25%" valign="top" bgcolor="#F2F2F2" style="font-size:11pt; border:1px solid green;">
        <xsl:value-of select="Data1"/>
      </td>
      <td width="25%" valign="top" bgcolor="#D8D8D8" style="font-weight: bold; font-size:11pt; border:1px solid green;">
        <xsl:value-of select="Label2"/>
      </td>
      <td width="25%" valign="top" bgcolor="#F2F2F2" style="font-size:11pt; border:1px solid green;">
        <xsl:value-of select="Data2"/>
      </td>
    </xsl:if>
    <xsl:if test ="Label1[.!=''] and Data1[.!=''] and Label2[.='@#$%^'] and Data2[.='@#$%^']">
 <xsl:if test ="../@Type='Record' and ../@Desc=''">
  <td></td>
 </xsl:if>
      
   <td width="25%" valign="top" bgcolor="#D8D8D8" style="font-weight: bold; font-size:11pt; border:1px solid green;">
        <xsl:value-of select="Label1"/>
      </td>
      <td width="75%" valign="top" bgcolor="#F2F2F2" colspan="3" style="font-size:11pt; border:1px solid green;">
        <xsl:value-of select="Data1"/>
      </td>
    </xsl:if>
  </xsl:if>
  <xsl:if test ="@Type='List'">
    <td></td>
    <td width="100%" valign="top" style="font-weight: bold; font-size:11pt; border:1px solid green;" colspan="4" bgcolor="#A9BCF5">
      <xsl:value-of select="@Desc"/>
    </td>
  </xsl:if>
</xsl:template>
</xsl:stylesheet>

No comments:

Post a Comment