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 June 20th, 2008, 05:27 AM
Authorized User
 
Join Date: May 2008
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
Default Global parameter calculation inside template

Hello.
Is the following possible:
- define global parameter;
- assign a value to it inside a template;
- use this value of a parameter in the global level context.

smth like:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="var"/>
    <xsl:template match="/">
        <root>
            <node1>1</node1>
            <xsl:call-template name="aaa"/>
            <node3>
                <xsl:value-of select="$var"/>
            </node3>
        </root>
    </xsl:template>
    <xsl:template name="aaa">
        <xsl:with-param name="var" select="3"/>
        <node2>2</node2>
    </xsl:template>
</xsl:stylesheet>
to get the following result:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <node1>1</node1>
    <node2>2</node2>
    <node3>3</node3>
</root>
 
Old June 20th, 2008, 05:33 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

No, XSLT is a declarative functional language not a procedural one.

Describe your problem, rather than your procedural approach to solving it, and we might be able to help you.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 20th, 2008, 06:49 AM
Authorized User
 
Join Date: May 2008
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Describe your problem, rather than your procedural approach to solving it, and we might be able to help you.
ok, if to simplify it a lot I have an XML:
Code:
<?xml version="1.0" encoding="windows-1251"?>
<?xml-stylesheet type="text/xsl" href="test_xsl.xsl" indent="yes" encoding="Windows-1251"?>
<root>
    <status>
        <name>START</name>
        <date>1</date>
    </status>
    <status>
        <name>END</name>
        <date>3</date>
    </status>
    <status>
        <name>START</name>
        <date>5</date>
    </status>
</root>
I need to get a new XML with information about latest START date and latest END date. But I need latest END date only in case it is later than latest START date.

So in my case the result would be:
Code:
  <?xml version="1.0" encoding="UTF-8" ?> 
- <root>
  <latest_START>5</latest_START> 
  <latest_END/>
  </root>
END date is empty, because we don't have it after latest START date.

I used XSL to find both latest dates:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="root">
        <root>
            <latest_START>
                <xsl:apply-templates select="status[name='START']">
                    <xsl:sort select="date" order="descending"/>
                </xsl:apply-templates>
            </latest_START>
            <latest_END>
                <xsl:apply-templates select="status[name='END']">
                    <xsl:sort select="date" order="descending"/>
                </xsl:apply-templates>
            </latest_END>
        </root>
    </xsl:template>
    <xsl:template match="status">
        <xsl:if test="position()=1">
            <xsl:value-of select="date"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
but in this case the latest END is incorrect.
I wanted to capture latest START date into variable and use it in:
Code:
<xsl:apply-templates select="status[name='END' and date>$last_START_date]">
 
Old June 20th, 2008, 07:04 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

If you are using XSLT 2.0 then you can make use of the max function e.g.
Code:
<xsl:variable name="maxStart"
              select="max(/root/status[name = 'START']/date)"/>
<xsl:variable name="maxEnd"
              select="max(/root/status[name = 'END']/date)"/>
then you can simply compare
Code:
$maxStart > $maxEnd

--
  Martin Honnen
  Microsoft MVP - XML
 
Old June 20th, 2008, 07:16 AM
Authorized User
 
Join Date: May 2008
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Originally posted by Martin Honnen
 If you are using XSLT 2.0 then you can make use of the max function e.g.
 sorry, forgot to mention - version 1.0
but still I can implement your solution through <xsl:for-each>+<xsl:sort>+position()=1

but still is there a simpler solution, than using 2 variables?
And I didn't want to use <xsl:for-each> and wanted to use it through <xsl:apply-templates>.

 
Old June 20th, 2008, 07:27 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

You can write a template to perform the 'max' functionality, much like EXSLT has here:

http://www.exslt.org/math/functions/...x.template.xsl

<xsl:variable name="maxStart">
 <xsl:call-template name="math:max">
  <xsl:with-param name="nodes" select="/root/status[name = 'START']/date"/>
 </xsl:call-template>
</xsl:variable>

/- Sam Judson : Wrox Technical Editor -/
 
Old June 20th, 2008, 07:35 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Here is an adaption of the stylesheet you posted:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="root">
        <root>
            <xsl:variable name="latest_start">
                <xsl:apply-templates select="status[name='START']">
                    <xsl:sort select="date" order="descending"/>
                </xsl:apply-templates>
            </xsl:variable>
            <latest_START>
              <xsl:value-of select="$latest_start"/>
            </latest_START>
            <latest_END>
                <xsl:apply-templates select="status[name='END' and date &gt; $latest_start]">
                    <xsl:sort select="date" order="descending"/>
                </xsl:apply-templates>
            </latest_END>
        </root>
    </xsl:template>
    <xsl:template match="status">
        <xsl:if test="position()=1">
            <xsl:value-of select="date"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
Applied to the sample input you posted earlier it outputs
Code:
<root>
   <latest_START>5</latest_START>
   <latest_END/>
</root>
--
  Martin Honnen
  Microsoft MVP - XML
 
Old June 20th, 2008, 07:50 AM
Authorized User
 
Join Date: May 2008
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:
Here is an adaption of the stylesheet you posted:
thanks - I was so near :)
it is always useful to have a fresh look at it.

 
Old June 20th, 2008, 08:10 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

If the status events are always in order, then you don't need to use max() or sorting. You can just select the last one by position. The last START (assuming <root> as context item) is select="status[name='START'][last()]"; similarly the last END; you can test whether the last start has a following END using <xsl:if test="status[name='START'][last()]/following-sibling::status[name='END']"/>.

Certainly, this a problem that doesn't need procedural logic at all; the output can be described fairly easily as a function of the input.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
Change Text of Textbox inside Template DarkForce ASP.NET 2.0 Basics 3 September 14th, 2012 07:11 AM
value-of inside template match RoeZ XSLT 5 April 17th, 2008 12:09 PM
Problem accessing global variable inside functions jedijr88 Beginning PHP 3 June 29th, 2007 12:51 PM
TEMPLATE CALCULATION pallone XSLT 7 December 22nd, 2006 07:20 PM
USING PARAMETER INSIDE XSL:TEXT cleytonjordan XSLT 6 July 29th, 2005 07:30 PM





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