XML Editor
Sign up for a WebBoard account Sign Up Keyword Search Search More Options... Options
Chat Rooms Chat Help Help News News Log in to WebBoard Log in Not Logged in
Show tree view Topic
Topic Page 1 2 3 4 5 6 7 8 9 Go to previous topicPrev TopicGo to next topicNext Topic
Postnext
educated idiotSubject: XSLT Math operations help
Author: educated idiot
Date: 10 Aug 2004 11:00 PM
Suppose I have an XML file that looks like this:
<A>
<VAL id="001">2</VAL>
<VAL id="233">4</VAL>
<VAL id="466">8</VAL>
</A>
<B>
<VAL id="001">2</VAL>
<VAL id="233">1</VAL>
<VAL id="466">4</VAL>
</B>

Is it possible to use XSLT to divide the first val in A by the first val
in B, and so on? The id attribute is not known at design-time, however:
- the first node is always divided by the first node in the other group, and so on
- the id attributes of these elements always match
- the id attributes in each of the two groups are unique

The desired output in this example would be:
<OUTPUT>
<OUT>1</OUT>
<OUT>4</OUT>
<OUT>2</OUT>
</OUTPUT>

Anyone have any ideas if and how this can be accomplished?

Any help would be much appreciated!

Postnext
Ivan PedruzziSubject: XSLT Math operations help
Author: Ivan Pedruzzi
Date: 10 Aug 2004 11:44 PM
You must have a root nodein your input document, i called root:

<?xml version="1.0"?>
<root>
<A>
<VAL id="001">2</VAL>
<VAL id="233">4</VAL>
<VAL id="466">8</VAL>
</A>
<B>
<VAL id="001">2</VAL>
<VAL id="233">1</VAL>
<VAL id="466">4</VAL>
</B>
</root>

then you can do something like that

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="B" match="root/B/VAL" use="@id"/>

<xsl:template match="/">
<OUTPUT>
<xsl:apply-templates select="root/A"/>
</OUTPUT>
</xsl:template>

<xsl:template match="text()"/>

<xsl:template match="VAL">
<OUT><xsl:value-of select=". div key('B',@id)"/></OUT>
</xsl:template>

</xsl:stylesheet>

Postnext
educated idiotSubject: XSLT Math operations help
Author: educated idiot
Date: 11 Aug 2004 11:12 PM
Thank you! I was not familiar with the <xml:key /> syntax. It works like
a charm.

Any suggestions on how to handle an extension to this problem? :
<root>
<A>
<VAL id="001">2</VAL>
<VAL id="233">4</VAL>
<VAL id="466">8</VAL>
</A>
<B>
<VAL id="001">2</VAL>
<VAL id="233">1</VAL>
<VAL id="466">4</VAL>
</B>
</root>

Now I would like to output the value of the first element in A divided by
the AVERAGE of the first two elements in B, and so on. Here is the desired
output:

<OUTPUT>
<OUT>0.667</OUT> <-- 2 / (2+1)
<OUT>0.8</OUT> <-- 4 / (1+4)
<OUT>-</OUT> <-- unable to compute
</OUTPUT>

I can't see a way to do this in XSLT, but I don't have much experience with the language.

Any ideas with this one?

Thanks again. Your help was much appreciated.

Postnext
Ivan PedruzziSubject: XSLT Math operations help
Author: Ivan Pedruzzi
Date: 12 Aug 2004 12:40 AM
I am not sure if you meant AVERANGE or SUM, but the following does what you described.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="B" match="root/B/VAL" use="@id"/>
<xsl:key name="A" match="root/A/VAL" use="@id"/>

<xsl:template match="/">
<OUTPUT>
<xsl:apply-templates select="root/A"/>
</OUTPUT>
</xsl:template>

<xsl:template match="text()"/>

<xsl:template match="VAL">
<xsl:for-each select="key('B',@id)">
<OUT>
<xsl:choose>
<xsl:when test="following-sibling::*[1]">
<xsl:value-of select="format-number(key('A',@id) div (. + following-sibling::*[1]), '###.###')"/>
</xsl:when>
<xsl:otherwise>-</xsl:otherwise>
</xsl:choose>
</OUT>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Ivan

Postnext
educated idiotSubject: XSLT Math operations help
Author: educated idiot
Date: 12 Aug 2004 09:42 PM
Thank you once again.

Another extension to this problem. I was using the following-sibling notation
to retrieve the next sibling from ONE element. Now I would like to retrieve
another element with this same id from another node. I cannot seem to figure
out how to retrieve the value of the id attribute from this "next-sibling" node
so that I can pass it into a key() function (or whatever that syntax is referred to as).

A new XML file:
<root>
<A>
<VAL id="001">2</VAL>
<VAL id="233">4</VAL>
<VAL id="466">8</VAL>
</A>
<B>
<VAL id="001">2</VAL>
<VAL id="233">1</VAL>
<VAL id="466">4</VAL>
</B>
<C>
<VAL id="001">6</VAL>
<VAL id="233">7</VAL>
<VAL id="466">8</VAL>
</C>
</root>

For example, suppose I would like to divide the first element in A by the
sum of the 2nd elements in B and C. [ 2 / ( 1 + 7 ) ] I would then continue
in a loop as before -- divide the second element in A by the sum of the 3rd
elements in B and C.

I imagine this shouldn't be difficult using the building blocks you have already
shown me, but I can't seem to figure it out.

Thanks once again for your help.

Postnext
educated idiotSubject: XSLT Math operations help
Author: educated idiot
Date: 21 Aug 2004 12:14 PM
Is this not possible?

To summarize in case I wasn't clear:
Given an element, is it possible to retrieve its next sibling AND an
element in another node with the same id attribute, so that a math operation
can be performed on the two values?

If anyone has a lot of experience with XSL and thinks this is impossible,
I'd appreciate the opinion so that I can move on and look for a workaround.
This SEEMS like it should be possible, but with my lack of experience I can't
seem to figure it out.

Thanks once again for all the help.

Postnext
Ivan PedruzziSubject: XSLT Math operations help
Author: Ivan Pedruzzi
Date: 22 Aug 2004 06:03 PM
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="C" match="root/C/VAL" use="@id"/>
<xsl:key name="B" match="root/B/VAL" use="@id"/>
<xsl:key name="A" match="root/A/VAL" use="@id"/>

<xsl:template match="/">
<OUTPUT>
<xsl:apply-templates select="root/A"/>
</OUTPUT>
</xsl:template>

<xsl:template match="text()"/>

<xsl:template match="VAL">
<OUT>
<xsl:choose>
<xsl:when test="key('B',@id) and key('C',@id)">
<xsl:value-of select="format-number(. div (key('B',@id) + key('C',@id)), '###.###')"/>
</xsl:when>
<xsl:otherwise>-</xsl:otherwise>
</xsl:choose>
</OUT>
</xsl:template>
</xsl:stylesheet>

Posttop
Ivan PedruzziSubject: XSLT Math operations help
Author: Ivan Pedruzzi
Date: 25 Aug 2004 10:42 PM
The previous solution was obviously incorrect
Hopefully this was does what you want.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="C" match="root/C/VAL" use="@id"/>
<xsl:key name="B" match="root/B/VAL" use="@id"/>

<xsl:template match="/">
<OUTPUT>
<xsl:apply-templates select="root/A"/>
</OUTPUT>
</xsl:template>

<xsl:template match="text()"/>

<xsl:template match="VAL">
<OUT>

<xsl:variable name="B">
<xsl:for-each select="key('B',@id)">
<xsl:value-of select="number(following-sibling::VAL[1])"/>
</xsl:for-each>
</xsl:variable>

<xsl:variable name="C">
<xsl:for-each select="key('C',@id)">
<xsl:value-of select="number(following-sibling::VAL[1])"/>
</xsl:for-each>
</xsl:variable>

<xsl:choose>
<xsl:when test="$B!='NaN' and $C!='NaN'">
<xsl:value-of select="format-number(. div ($B + $C), '###.###')"/>
</xsl:when>
<xsl:otherwise>-</xsl:otherwise>
</xsl:choose>
</OUT>
</xsl:template>
</xsl:stylesheet>

 
Topic Page 1 2 3 4 5 6 7 8 9 Go to previous topicPrev TopicGo to next topicNext Topic
Download A Free Trial of Stylus Studio 6 XML Professional Edition Today! Powered by Stylus Studio, the world's leading XML IDE for XML, XSLT, XQuery, XML Schema, DTD, XPath, WSDL, XHTML, SQL/XML, and XML Mapping!  
go

Log In Options

Site Map | Privacy Policy | Terms of Use | Trademarks
Stylus Scoop XML Newsletter:
W3C Member
Stylus Studio® and DataDirect XQuery ™are from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2016 All Rights Reserved.