Solved

Serial number in XSLT

Posted on 2007-03-28
20
1,249 Views
Last Modified: 2013-11-18

I have an XML such as

<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<package>
    <document>
        <document_metadata>
            <first_name>ABC</first_name>
            <middle_name/>
            <last_name>XYZ</last_name>
            <appl>Appl1</appl>
        </document_metadata>

            <document_content>
            <author>
                <year>1895</year>
                <biog></biog>
            </author>
        </document_content>
    </document>

    <document>
        <document_metadata>
            <first_name>Tim</first_name>
            <middle_name/>
            <last_name>Hall</last_name>
            <appl>Appl2</appl>
        </document_metadata>
        <document_content>
                <year>1985</year>
                <biog></biog>
        </document_content>
    </document>

</package>

I need to transform it to an HTML table, which has 5 columns
Serial No. --> Serial No.
Appl --> value of <appl> element
Last --> Value of <last_name> element
Middle -->  Value of <middle_name> element
First --> Value of <first_name> element

I have written the following XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="package">
        <table border="2">
            <tr bgcolor="#C0C0C0">
                <th>Serial No.</th>
                <th>Appl</th>
                <th>Last</th>
                <th>Middle</th>
                <th>First</th>
            </tr>

                <xsl:apply-templates/>
           
        </table>

    </xsl:template>
   
    <xsl:template match="document" >
        <xsl:apply-templates select="document_metadata" />
    </xsl:template>
   
    <xsl:template match="document_metadata">
        <tr>
            <td>111</td>
            <td>
                <xsl:value-of select="appl"/>
            </td>
            <td>
                <xsl:value-of select="last_name"/>
            </td>
            <td>
                <xsl:choose>
                    <xsl:when test="middle_name=''"></xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="middle_name"/>
                    </xsl:otherwise>
                </xsl:choose>
               
            </td>
            <td>
                <xsl:value-of select="first_name"/>
            </td>
        </tr>
    </xsl:template>
   
   
</xsl:stylesheet>

Two things I am unable to do are:
1. Generate a serial no. How to count which row it is. Serial no. will be in the form of 1,2,3 and so on
2. Most of the <middle_name> elements are empty. In my HTML table I have given the border as 2. In HTML When the cells are empty even the border is not displayed. I want to display the border even for empty cells. If we put &nbsp; in an empty cell then the border is displayed. So if I do

<td>
                <xsl:choose>
                    <xsl:when test="middle_name=''">&nbsp;</xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="middle_name"/>
                    </xsl:otherwise>
                </xsl:choose>
               
            </td>
it gives me an error.

Please tell me how to solve these.
0
Comment
Question by:Annabelle_s
20 Comments
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18813916
1. use  <td><xsl:number count="document"/></td> to count the documents

2. if you want to output &nbsp; you need to define the entity in the XSLT and in the resulting XML
You could use &#160; which is the same thing but can be used without declaration

   <xsl:template match="document_metadata">
        <tr>
            <td><xsl:number count="document"/></td>
            <td>
                <xsl:value-of select="appl"/>
            </td>
            <td>
                <xsl:value-of select="last_name"/>
            </td>
            <td>
                <xsl:choose>
                    <xsl:when test="middle_name=''">&#160;</xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="middle_name"/>
                    </xsl:otherwise>
                </xsl:choose>
           </td>
            <td>
                <xsl:value-of select="first_name"/>
            </td>
        </tr>
    </xsl:template>

cheers

Geert
0
 

Author Comment

by:Annabelle_s
ID: 18813946

>>use  <td><xsl:number count="document"/></td> to count the documents
It displays 1 for each row. The serial number should be incremented for each row
0
 

Author Comment

by:Annabelle_s
ID: 18813955
>>It displays 1 for each row. The serial number should be incremented for each row

i am sorry, its working fine. Old result might be getting cached. i restarted the browser and its working fine. Thanks
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18813962
welcome
0
 

Author Comment

by:Annabelle_s
ID: 18813982
There's another small problem. I want the alternate rows to be displayed in different colors. So I was trying to do

<xsl:template match="document_metadata">
        <xsl:variable name="count">
            <xsl:number count="document"/>
        </xsl:variable>
        <xsl:variable name="backGround">
            <xsl:choose>
                <xsl:when test="count div 2=0">
                    #C0C0C0;
                </xsl:when>
                <xsl:otherwise>
                    #D2E8E8;
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <tr bgcolor="$backGround">
            <td><xsl:number count="document"/></td>
            <td>
                <xsl:value-of select="appl"/>
            </td>

But all the rows are getting displayed in the same color
0
 

Author Comment

by:Annabelle_s
ID: 18814039
if I try to print

Mod result--<xsl:value-of select="count mod 2"></xsl:value-of>        

i get NaN. What the reason for getting NaN
0
 

Author Comment

by:Annabelle_s
ID: 18814041
>>Mod result--<xsl:value-of select="count mod 2"></xsl:value-of>        
Sorry it should have been

Mod result--<xsl:value-of select="$count mod 2"></xsl:value-of>        
0
 

Author Comment

by:Annabelle_s
ID: 18814059
If I do
        Mod result--<xsl:value-of select="$count mod 2=0"></xsl:value-of>    

It prints alterante true and false. But then why doesnt the when/otherwise statement work.
0
 

Author Comment

by:Annabelle_s
ID: 18814077
Even when I print
        BackGround--<xsl:value-of select="$backGround"></xsl:value-of>
i get alternate value. But can't see the correct results. All rows are dispalying with the same color.
0
 

Author Comment

by:Annabelle_s
ID: 18814082
I think doing this will not work

<tr bgcolor="$backGround">

Since <tr> is an HTML tag and $backGround is an XSLT variable. Am I correct? Then whats the way to do it.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18814101
I was bringing the kids to school, so I missed part of the conversation

   <xsl:template match="document_metadata">
        <xsl:variable name="rowCount">
            <xsl:number count="document"/>
        </xsl:variable>
        <tr>
            <xsl:attribute name="bgcolor">
                <xsl:choose>
                    <xsl:when test="$rowCount mod 2 = 1">red</xsl:when>
                    <xsl:otherwise>yellow</xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
           
            <td><xsl:value-of select="$rowCount"></xsl:value-of></td>

works for me, on the condition that you set the XSLT version to 1.0
XSLT2.0 doesn't do automatic casting between types, because of the strong typing
and xsl:number creates a string, not a number, hence NaN

If you don't use XSLT2 constructs, set the version to 1
otherwise make an explicit cast,
I will show that in a minute

cheers

Geert
0
 
LVL 8

Expert Comment

by:thomas908
ID: 18814108
This works for me, with the code you posted
        <tr bgcolor="{$backGround}">
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18814109
<tr bgcolor="$backGround">
will output the literal string $background
you need to use attribute value templates
in order to evaluate the XPath
<tr bgcolor="{$backGround}">

cheers

Geert
0
 

Author Comment

by:Annabelle_s
ID: 18814130
>><tr bgcolor="{$backGround}">
This works fine. It displays alternate rows in differnet colors.
But why is the color display so different

The color display when I do this
<tr bgcolor="#D2E8E8">
 <td>Serial No.</td>

is totally different from

        <tr bgcolor="{$backGround}">
with the same value of $backGround, that is   #D2E8E8
Also, in Firefox, alterante coloring is not working
           
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18814134
Forget my casting comment,
aparently xsl:number returns an integer
so all is OK
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18814137
Is this processing in a browser?
If it is you have to set the stylesheet version to 1.0,
browsers don't support 2.0 and sometimes act funny on the wrong version number

cheers

Geert
0
 

Author Comment

by:Annabelle_s
ID: 18814150
I did this
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output version="1.0" method="html" encoding="ISO-8859-1" />

Now it works fine in Firefox but coloring is still messed up in IE6
0
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 200 total points
ID: 18814168
instead of <tr bgcolor="{$backGround}">

can you try this?

<tr style="background-color: {$backGround};">
0
 

Expert Comment

by:unifi
ID: 25043020

<cell>
<xsl:value-of select="position()"/>
</cell>
is the easiest way to generate serial numbers :)
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 25043089
> is the easiest way to generate serial numbers :)

this question has been long closed by the way....

but you are only right in a very specific case,
if position() acts upon a nodeset that is only the document

In the example above, position() would not have worked for various reasons
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Preface This article introduces an authentication and authorization system for a website.  It is understood by the author and the project contributors that there is no such thing as a "one size fits all" system.  That being said, there is a certa…
What is Node.js? Node.js is a server side scripting language much like PHP or ASP but is used to implement the complete package of HTTP webserver and application framework. The difference is that Node.js’s execution engine is asynchronous and event…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now