Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
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 October 29th, 2004, 04:41 AM
Registered User
 
Join Date: Oct 2004
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default Accessing values from the last sibling node

Given the XML

<OrderLine>
    <Plot>01</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget A</Product>
</OrderLine>
<OrderLine>
    <Plot>01</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget B</Product>
</OrderLine>
<OrderLine>
    <Plot>02</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget C</Product>
</OrderLine>
<OrderLine>
    <Plot>02</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget D</Product>
</OrderLine>

I want to produce output

Plot 01 - Widget Kit
Widget A
Widget B
Plot 02 - Widget Kit
Widget C
Widget D

i.e. if the value of the <Plot> element has changed from the previous <OrderLine> element, display the values of the <Plot> and <Kit> elements. To do this I need to access the <Plot> value from the previous <OrderLine>

The <OrderLine> elements will always be in <Plot> order.

My xsl looks like

<xsl:apply-templates select="//OrderLine">

<xsl:template match="//OrderLine">
    <xsl:for-each select=".">
        <xsl:if test="not(contains(Plot, ./preceding-sibling::Plot[position()=1))">
            <xsl:value-of select="Plot"> - <xsl:value-of select="Kit">
        </xsl:if>
        <xsl:value-of select="Product">
    </xsl:for-each>
</xsl:template>

However, all I get is

Widget A
Widget B
Widget C
Widget D

The if statement is never true

Any help would be much appreciated, I'm tearing my hair out here :(


 
Old October 29th, 2004, 05:14 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Given this xml:
Code:
<Order>
  <OrderLine>
    <Plot>01</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget A</Product>
  </OrderLine>
  <OrderLine>
    <Plot>01</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget B</Product>
  </OrderLine>
  <OrderLine>
    <Plot>02</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget C</Product>
  </OrderLine>
  <OrderLine>
    <Plot>02</Plot>
    <Kit>Widget Kit</Kit>
    <Product>Widget D</Product>
  </OrderLine>
</Order>
You could try this: (I didn't use for-each as it's not needed in your example:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:apply-templates select="Order/OrderLine"/>  
  </xsl:template>
  <xsl:template match="OrderLine">    
    <xsl:if test="not(Plot = preceding-sibling::*[1]/Plot)">
      <xsl:value-of select="Plot"/> - <xsl:value-of select="Kit"/><xsl:text>#xa;</xsl:text>
    </xsl:if>
    <xsl:text>#x9;</xsl:text><xsl:value-of select="Product"/><xsl:text>#xa;</xsl:text>    
  </xsl:template>
</xsl:stylesheet>
Personally I wouldn't do it this way, I would use Muenchian grouping, that way you don't need to rely on the Plot elements being sorted.



--

Joe (Co-author Beginning XML, 3rd edition)
 
Old October 29th, 2004, 06:06 AM
Registered User
 
Join Date: Oct 2004
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks very much, that works a treat with one minor change.

I amended the line

<xsl:if test="not(Plot = preceding-sibling::*[1]/Plot)">

to read

<xsl:if test="not(Plot = preceding-sibling::OrderLine[1]/Plot)">

Not sure if this is because I didn't post my complete source XML or some other reason.

Anyhow, it works now, I can enjoy the rest of my Friday afternoon now

Thanks again
Gray

 
Old October 29th, 2004, 06:15 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Quote:
quote:Originally posted by graywoodhouse
 Thanks very much, that works a treat with one minor change.

I amended the line

<xsl:if test="not(Plot = preceding-sibling::*[1]/Plot)">

to read

<xsl:if test="not(Plot = preceding-sibling::OrderLine[1]/Plot)">

Not sure if this is because I didn't post my complete source XML or some other reason.

Anyhow, it works now, I can enjoy the rest of my Friday afternoon now

Thanks again
Gray
Should be the same unless you have other elements at the same level in the hierarchy as the OrderLine ones.

Have a good weekend.



--

Joe (Co-author Beginning XML, 3rd edition)





Similar Threads
Thread Thread Starter Forum Replies Last Post
XPath to get next node (sibling) jeft0nes XSLT 2 August 8th, 2007 08:30 PM
Getting distinct sibling values from a key Chris Cash XSLT 2 June 19th, 2006 05:03 PM
Accessing data From a node austinf XML 1 June 7th, 2006 02:16 AM
MDI Sibling calling Sibling... Nick.Net VB.NET 2002/2003 Basics 1 December 8th, 2003 09:23 PM
Accessing XML Node with multiple namespaces bamirzada C# 0 August 14th, 2003 07:41 PM





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