Serial number in XSLT


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.
Annabelle_sAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Geert BormansInformation ArchitectCommented:
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
Annabelle_sAuthor Commented:

>>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
Annabelle_sAuthor Commented:
>>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
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

Geert BormansInformation ArchitectCommented:
welcome
0
Annabelle_sAuthor Commented:
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
Annabelle_sAuthor Commented:
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
Annabelle_sAuthor Commented:
>>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
Annabelle_sAuthor Commented:
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
Annabelle_sAuthor Commented:
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
Annabelle_sAuthor Commented:
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
Geert BormansInformation ArchitectCommented:
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
thomas908Commented:
This works for me, with the code you posted
        <tr bgcolor="{$backGround}">
0
Geert BormansInformation ArchitectCommented:
<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
Annabelle_sAuthor Commented:
>><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
Geert BormansInformation ArchitectCommented:
Forget my casting comment,
aparently xsl:number returns an integer
so all is OK
0
Geert BormansInformation ArchitectCommented:
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
Annabelle_sAuthor Commented:
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
Geert BormansInformation ArchitectCommented:
instead of <tr bgcolor="{$backGround}">

can you try this?

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
unifiCommented:

<cell>
<xsl:value-of select="position()"/>
</cell>
is the easiest way to generate serial numbers :)
0
Geert BormansInformation ArchitectCommented:
> 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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.