Wrox Programmer Forums
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old November 19th, 2010, 07:05 AM
Registered User
 
Join Date: Nov 2010
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
Default xslt

I have an xml in the following way
<emps>
<emp>
<Department>A<Department>
<Name>Archana<Name>
<AccountNumber>12<AccountNumber>
<Title>Developer<Title>
<emp>
</emps>

I need to create a xslt which will have to data in the following format
Display the records in four columns

fill first 50 rows(include the department name)-row1-50 column 1
fill next 50 rows (include the department name)-row1-50 column 2
fill next 50 rows (include the department name)-row1-50 column 3
fill next 50 rows (include the department name)-row1-50 column 4

<div style="float:left">
department A----row1
Archana---------row2
Devi

department B
devi
shreya
Name2
---------------after 50 rows
<div>
<div style="float:left">
---next 50 rows
</div>
I was able to do group by and get the records. But I am not able to add the div tags after 50 rows.

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

<xsl:output omit-xml-declaration="yes" indent="yes"/>


<xsl:key name="kTitleBy1stLetter" match="emps/emp" use="Department"/>

<xsl:template match="/*">
<div style="float:left">
<xsl:for-each select="emp [generate-id() = generate-id(key('kTitleBy1stLetter', Department) [1] ) ]">
<xsl:variable name="v1st" select="Department"/>
<h2><xsl:value-of select="$v1st"/></h2>


<xsl:for-each select="key('kTitleBy1stLetter',$v1st)">
<xsl:value-of select="Name"/>
</xsl:for-each>


</xsl:for-each>
</div>
</xsl:template>
</xsl:stylesheet>
Please help.
Thanking you,

SMP
 
Old November 19th, 2010, 07:31 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

>But I am not able to add the div tags after 50 rows.

You don't solve grouping problems in XSLT by "adding tags". XSLT outputs a tree of nodes, not a string of tags. The logic needs to be "for each group of 50 consecutive input elements, create an output element and add it to the tree".

Look at some of the examples here, especially the first:

http://www.dpawson.co.uk/xsl/sect2/N4486.html
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old November 19th, 2010, 04:06 PM
Registered User
 
Join Date: Nov 2010
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
Default How to add the department and still able to find when 50 rows are reached

Hi Michael Kay,

Thank you for your immediate response. As per your advice I modified my xslt to count the records. If I do that way, I am able to add only the Names. But how do I add the department and still able to find the 50 th record. Please help

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>

<xsl:output method="html" indent="yes" />

<xsl:template match="/emps/emp">


<xsl:choose>
<xsl:when test="position() = 1">
<xsl:text disable-output-escaping="yes">
&lt;div style="float:left"&gt;</xsl:text>
<br/>
<xsl:value-of select="position()"/>
<xsl:value-of select="Name"/>
<br/>
</xsl:when>
<xsl:when test="position() = last()">
<xsl:value-of select="position()"/>
<xsl:value-of select="Name"/>
<xsl:text disable-output-escaping="yes">
&lt;/div&gt;
</xsl:text>
</xsl:when>
<xsl:when test="position() mod 3 = 0">
<xsl:value-of select="position()"/>
<xsl:value-of select="Name"/>

<br/>
<xsl:text disable-output-escaping="yes">
&lt;/div&gt;
&lt;div style="float:left"&gt;</xsl:text>
<br/>

</xsl:when>
<xsl:otherwise>
<xsl:text></xsl:text>
<xsl:value-of select="position()"/>
<xsl:value-of select="Name"/>
<br/>

</xsl:otherwise>
</xsl:choose>



</xsl:template>

</xsl:stylesheet>



XML FILE

<?xml version="1.0" encoding="utf-8" ?>
<emps>
<emp>
<Department>
A
</Department>
<Name>
Archana
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
<emp>
<Department>
A
</Department>
<Name>
Acharya
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
<emp>
<Department>
A
</Department>
<Name>
Madumitha
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
<emp>
<Department>
B
</Department>
<Name>
Madumitha
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
<emp>
<Department>
C
</Department>
<Name>
Madumitha
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
<emp>
<Department>
D
</Department>
<Name>
Madumitha
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
<emp>
<Department>
D
</Department>
<Name>
John
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
<emp>
<Department>
D
</Department>
<Name>
David
</Name>
<AccountNumber>
12
</AccountNumber>
<Title>
Developer
</Title>
</emp>
</emps>
 
Old November 19th, 2010, 07:41 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Well first, get rid of that disable-output-escaping nonsense. You're still trying to write tags to the output, which isn't the way XSLT works.

Then read the examples in the FAQ again - it's clear you haven't understood the principles.

I don't really understand why you are having difficulty outputting the department name.

Your logic should be something like this:

Code:
<xsl:for-each select="emp[position() mod 50 = 1]">
  <div>
    <xsl:for-each select="(. | following-sibling::emp)[position &lt;= 50]">
      <xsl:value-of select="Department"/>
      <xsl:value-of select="Name"/>
    </xsl:for-each>
  </div>
</xsl:for-each>
plus some formatting.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old November 20th, 2010, 12:56 AM
Registered User
 
Join Date: Nov 2010
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
Default XSLT

I greatly appreciate your help. I am a .net programmer. I have written xslt's to filter records. This is the first time I am need to know and do little bit more about. But since requirements to write these types have become more frequent recently , I am trying to learn it.

As a first step, I bought your book "XSLT 2.0 and Xpath 2.0". After viewing your suggestion and reading your book I was able to understand 'following-sibling'. Diagrams used to explain Axis steps was superb.
But for this project I am using XSLT 1.0.

I tried to run your code in xslt 1.0 and it is not working. Please help.

The code I used is

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="html" />
<xsl:template match="/emps">
<xsl:for-each select="emp[position() mod 3 = 1]">
<div style="float:left">
<xsl:for-each select="(. | following-sibling::emp)[position &lt;= 3]">
<xsl:value-of select="Department"/>
<xsl:value-of select="Name"/>
</xsl:for-each>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
 
Old November 20th, 2010, 05:53 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

Your second position is missing the parenthesis - position().
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old November 20th, 2010, 09:43 AM
Registered User
 
Join Date: Nov 2010
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
Default XSLT-Need to group by department

Hi samjudson,

Thanks for your response.

I need to group by department and still be able to find the 50 th row, so I can move to next column.
 
Old November 20th, 2010, 09:48 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

I don't understand your problem. Simply change the 3 to 50 and that should do it.

If that doesn't produce the output you are after then you need to explain why.
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old November 20th, 2010, 10:02 AM
Registered User
 
Join Date: Nov 2010
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
Default XSLT

With the current code
With the given code, I get the results like

Deparment Name
Department Name

But I need

Deparment
Name
Name
Name

Department
Name
Name

Since the Deparment is not showing everytime, I am not able to count the exact amount of rows that is already there. Because Position does not exclude the department when it is not shown
 
Old November 21st, 2010, 01:03 PM
Registered User
 
Join Date: Nov 2010
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
Default XSLT-the solution

Hi Michael Kay and Samjudson,

Thank you for your help to help me to solve. I was able write a code which gives the desired result. I am curious to know whether I can improve it. Please suggest.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="html" indent="yes"/>
<xsl:param name="Count" select="3"></xsl:param>
<xsl:key name="kTitleBy1stLetter" match="emps/emp" use="Department"/>

<xsl:template match="/*">

<div style="float:left" width="500px">
<xsl:for-each select="emp [generate-id() = generate-id(key('kTitleBy1stLetter', Department) [1] ) ]">
<xsl:variable name="v1st" select="Department"/>
<xsl:variable name="StaffCount" select="count(preceding-sibling::*)"/>
<xsl:variable name="TotalCount" select="number($StaffCount)+position()"/>

<xsl:value-of select="$v1st"/>
<xsl:choose>
<xsl:when test="($TotalCount mod $Count = 0)">
<xsl:call-template name="setTag"></xsl:call-template>
</xsl:when>
<xsl:otherwise>
<br/>
</xsl:otherwise>
</xsl:choose>
<xsl:variable name="getEachGroupCount" select="count(key('kTitleBy1stLetter',Department)) "/>
<xsl:choose>
<xsl:when test="$TotalCount &lt; $Count">

<xsl:variable name="TotalCount1" select="number($TotalCount)"/>
<xsl:variable name="GrandTotal" select ="number($getEachGroupCount)+number($TotalCount 1)"/>
<xsl:choose>
<xsl:when test="number($GrandTotal) &gt; $Count">
<xsl:for-each select="key('kTitleBy1stLetter',$v1st) [position() &lt;= number($Count)-number($TotalCount1)]">
<xsl:call-template name="StaffInfo"></xsl:call-template>
</xsl:for-each>
<xsl:call-template name="setTag"></xsl:call-template>

<xsl:for-each select="key('kTitleBy1stLetter',$v1st) [position() &gt; number($Count)-number($TotalCount1) ]">
<xsl:call-template name="StaffInfo"></xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="key('kTitleBy1stLetter',$v1st)">
<xsl:call-template name="StaffInfo"></xsl:call-template>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="TotalCount1" select="number($TotalCount) mod $Count"/>
<xsl:variable name="GrandTotal" select ="number($getEachGroupCount)+number($TotalCount 1)"/>
<xsl:choose>

<xsl:when test="number($GrandTotal) &gt; $Count">
<xsl:for-each select="key('kTitleBy1stLetter',$v1st) [position() &lt;= number($Count)-number($TotalCount1)]">
<xsl:call-template name="StaffInfo"></xsl:call-template>
</xsl:for-each>
<xsl:call-template name="setTag"></xsl:call-template>
<xsl:for-each select="key('kTitleBy1stLetter',$v1st) [position() &gt; number($Count)-number($TotalCount1)]">
<xsl:call-template name="StaffInfo"></xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="key('kTitleBy1stLetter',$v1st)">
<xsl:call-template name="StaffInfo"></xsl:call-template>
</xsl:for-each>
<xsl:if test="number($GrandTotal) = $Count">
<xsl:call-template name="setTag"></xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</div>

</xsl:template>
<xsl:template name="setTag">
<xsl:text disable-output-escaping="yes" >
&lt;/div&gt;
&lt;div style="float:left" width="500px"&gt;</xsl:text>

</xsl:template>
<xsl:template name="StaffInfo">
<xsl:value-of select="Name"/>
<br/>
</xsl:template>

</xsl:stylesheet>

Thanking you,

Marudha





Similar Threads
Thread Thread Starter Forum Replies Last Post
Another question about generating XSLT with XSLT danblick XSLT 2 July 16th, 2009 08:40 PM
Generating XSLT with XSLT stonis XSLT 3 April 1st, 2008 08:17 PM
General XSLT Questions in the XSLT Forum jminatel BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition ISBN: 978-0-470-19274-0 0 March 31st, 2008 07:50 PM
Can XSLT read DTD/schema and Generate XSLT.. ROCXY XSLT 1 November 6th, 2006 09:39 AM
dynamic xslt -> xslt creation namespace problem jkmyoung XSLT 2 July 15th, 2006 12:42 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.