Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > XML > XSLT
Password Reminder
Register
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
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 tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old February 24th, 2007, 02:33 PM
Friend of Wrox
Points: 1,676, Level: 16
Points: 1,676, Level: 16 Points: 1,676, Level: 16 Points: 1,676, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jul 2006
Location: , , .
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default Counting nodes on output

Hi, This questions is loosely related to post:
http://p2p.wrox.com/topic.asp?TOPIC_ID=56385

With thanks from Michael Kay, I was able to create a dynamic org chart.

With that in mind I am trying to count the nodes on output. I will eventually use these numbers to create a javascript treeview.

Here is my desired output in HTML:

Code:
   1  Technical Writer 
      2 Supervisor Publications – Development 
         3 Manager Publications 
            4 Director of Engineering 
               5 VP of Operations 
                 6 President


Here is how it outputs now:

Code:
   Technical Writer 
      Supervisor Publications – Development 
        Manager Publications 
            Director of Engineering 
               VP of Operations 
                  President


Here is the XML input:


Code:
<org>
    <position reportsto="Director of Engineering">Manager Publications</position>
    <position reportsto="Manager Publications">Supervisor Publications – Development </position>
    <position reportsto="Manager Publications">Supervisor Publications – Services</position>
    <position reportsto="Supervisor Publications – Development">Technical Writer</position>
    <position reportsto="Supervisor Publications –  Services">Publications Specialist</position>
    <position reportsto="VP of Operations">Director of Quality</position>
    <position reportsto="VP of Operations">Director of Engineering</position>
    <position reportsto="Director of Engineering">Manager Publications</position>

    <position reportsto="VP of Operations">Director of Quality</position>
    <position reportsto="Director of Quality">Manager Quality Assurance</position>
    <position reportsto="President">VP of Technical Operations</position>
</org>
XSLT:

Code:
<xsl:key name="mykey" match="position" use="."/>
    <xsl:variable name="XML" select="/"/>
    <xsl:template match="/">
        <html>
            <head>
                <title/>
            </head>
            <body>
                <xsl:for-each-group select="//position" group-by="@reportsto">
                    <xsl:apply-templates select="."/>
                </xsl:for-each-group>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="position">
        [list]
            <xsl:value-of select="."/>
            <xsl:for-each-group select="key('mykey', @reportsto)" group-by="@reportsto">
                <xsl:apply-templates select="."/>
            </xsl:for-each-group>
        </ul>
    </xsl:template>
The numbers will be used to create a hierarchy, therefore I can not use a normal list.

Thanks for the help.

Bones


Reply With Quote
  #2 (permalink)  
Old February 24th, 2007, 03:01 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I'm afraid that before considering the numbering, I'm having great difficulty understanding your present logic.

This:

  <xsl:for-each-group select="//position" group-by="@reportsto">
                    <xsl:apply-templates select="."/>
                </xsl:for-each-group>

applies templates to the first position in each group. Then this:

            <xsl:value-of select="."/>
            <xsl:for-each-group select="key('mykey', @reportsto)" group-by="@reportsto">
                <xsl:apply-templates select="."/>
            </xsl:for-each-group>

outputs that position, then selects those that report to this position, then groups them by who they report to (which is a null grouping, because they all report to the same person).

Can you explain what this orgchart is, and why not everyone is on it?

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #3 (permalink)  
Old February 24th, 2007, 03:20 PM
Friend of Wrox
Points: 1,676, Level: 16
Points: 1,676, Level: 16 Points: 1,676, Level: 16 Points: 1,676, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jul 2006
Location: , , .
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default

Hi Michael,

Its very possible my code is messed up. As I am trying to understand Keys and how they work. My thought process was I will eventually have a manual system with hundreds of policys. In those policys are positions (who owns the policy and who reports to who). The Org chart will display every position listed in a policy and then group, sort and show who they report to. (like the sample I gave). It works except for if the someone doesnt report to anyone (e.g. CEO) they will not show up. This is because the XSLT groups by @reportsto. So I changed the XSLT.



I left some information out by mistake. Here is my full output:


 
Code:
Manager Publications
Code:
 Director of Engineering 
  VP of Operations 
   President

Supervisor Publications –Development 
 Manager Publications 
  Director of Engineering 
   VP of Operations 
    President

Technical Writer 
 Supervisor Publications –Development 
  Manager Publications 
   Director of Engineering 
    VP of Operations 
     President

Technical Specialist 
 Supervisor Publications –Services 
  Manager Publications 
   Director of Engineering 
    VP of Operations 
     President
      Director of Quality 
       VP of Operations 
        President

Manager Quality Assurance / CASS 
 Director of Quality 
  VP of Operations 
   President

VP of Operations 
 President

President
Here is my Full XML:
Code:
<org>
    <position reportsto="Director of Engineering">Manager Publications</position>
    <position reportsto="Manager Publications">Supervisor Publications – Development </position>
    <position reportsto="Manager Publications">Supervisor Publications – Services</position>
    <position reportsto="Supervisor Publications – Development">Technical Writer</position>
    <position reportsto="Supervisor Publications –  Services">Publications Specialist</position>
    <position reportsto="VP of Operations">Director of Quality</position>
    <position reportsto="VP of Operations">Director of Engineering</position>
    <position reportsto="Director of Engineering">Manager Publications</position>

    <position reportsto="VP of Operations">Director of Quality</position>
    <position reportsto="Director of Quality">Manager Quality Assurance</position>
    <position reportsto="President">VP of Technical Operations</position>
    <position reportsto="CEO">President</position>
</org>
Revised XSLT:

Code:
<xsl:key name="mykey" match="position" use="."/>
    <xsl:variable name="XML" select="/"/>
    <xsl:template match="/">
        <html>
            <head>
                <title/>
            </head>
            <body>
                <xsl:for-each-group select="//position" group-by=".">
                    <xsl:apply-templates select="."/>
                </xsl:for-each-group>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="position">
        [list]
            <xsl:value-of select="current-grouping-key()"/>

            <xsl:for-each-group select="key('mykey', current()/@reportsto)" group-by="current()/@reportsto">

                <xsl:apply-templates select="."/>
            </xsl:for-each-group>
        </ul>
    </xsl:template>


Does this make more sense?

Your guidance is much appreciated.

Thanks,
Bones
Reply With Quote
  #4 (permalink)  
Old February 24th, 2007, 07:24 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

So logically what you are doing is:

for each person
  list all superiors in ascending order

Translated into XSLT that is

<!-- given a position, output its title
   and then recurse to process the superiors -->

<xsl:template match="person">
  <xsl:value-of select="."/>
  <xsl:apply-templates select="f:superior(.)"/>
</xsl:template>



<xsl:template match="/">
  <xsl:apply-templates select="//person"/>
</xsl:template>



<xsl:function name="f:superior">
  <xsl:param name="person" as="element(person)"/>
  <xsl:sequence select="key('r', @reportsto)"/>
</xsl:function>

<xsl:key name="r" match="person" select="."/>

No grouping involved.

If this is the logic, then you can do the numbering by passing a parameter on the recursive apply-templates call and incrementing its value on each call.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #5 (permalink)  
Old February 25th, 2007, 09:33 AM
Friend of Wrox
Points: 1,676, Level: 16
Points: 1,676, Level: 16 Points: 1,676, Level: 16 Points: 1,676, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jul 2006
Location: , , .
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default

Hi Michael,

You are correct. With my previous XSLT, I tried to pass a parameter on the recursive apply-templates call and incrementing its value on each call but it would return the order at which is was applied.

So I tried your last suggestion. I am getting a "context item undefined" in the following line:

<xsl:sequence select="key('r', @reportsto)"/>

Here is the XSLT:

Code:
    <xsl:key name="r" match="position" use="."/>
    <xsl:variable name="XML" select="/"/>
    <xsl:template match="/">
        <html>
            <head>
                <title/>
            </head>
            <body>
                <xsl:apply-templates select="//position"/>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="position">
            <xsl:value-of select="."/>
        <xsl:apply-templates select="f:superior(.)"/>
    </xsl:template>
    <xsl:function name="f:superior">
        <xsl:param name="person" as="element(position)"/>
        <xsl:sequence select="key('r', @reportsto)"/>
    </xsl:function>

It is very possible that I miss understand your suggestion.

Thanks again for the help

Reply With Quote
  #6 (permalink)  
Old February 25th, 2007, 10:32 AM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 100%
Activity: 100% Activity: 100% Activity: 100%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

SOrry about that, try

<xsl:sequence select="person/key('r', @reportsto)"/>


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #7 (permalink)  
Old February 26th, 2007, 08:19 PM
Friend of Wrox
Points: 1,676, Level: 16
Points: 1,676, Level: 16 Points: 1,676, Level: 16 Points: 1,676, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jul 2006
Location: , , .
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default

No worries and thank you very much for the help.

The XSLT only returns the elements in document order. However, I will figure it out. This how I learn.

You've been a great help.

Thank you,

Bones

Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Counting Nodes That Are Not Empty tommyready XSLT 2 September 4th, 2007 09:03 AM
Counting leaf nodes by transforming their value dmorin XSLT 3 June 29th, 2007 04:58 AM
Using axis instead of count? Counting child nodes. dep XSLT 1 January 17th, 2007 11:27 AM
adding prefix to nodes and subnodes to output xml raghurns XSLT 9 November 17th, 2006 04:41 PM
counting child nodes Tomi XSLT 1 September 6th, 2006 03:26 AM



All times are GMT -4. The time now is 02:39 PM.


Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.