Subject: Re: [xsl] params - keys? how to calculate product of parents with multiple children From: Dimitre Novatchev <dnovatchev@xxxxxxxxx> Date: Thu, 14 Apr 2005 06:33:21 +1000 |
On 4/14/05, Michael Kay <mike@xxxxxxxxxxxx> wrote: > > The first part, dividing the two (so-called) attributes is easy: > > RECORDITEM[@sqlsource='oldshares'] div RECORDITEM[@sqlsource='newshares'] > > The next bit is more difficult. There's no built-in function (like sum()) > that takes the product of a set of numbers, but Dimitre's FXSL library makes > it very easy to define one of your own. If he's listening, I'm sure he'll > tell you how. In XSLT 2.0 using FXSL one will simply use f:product and the whole transformation is the result of just a single XPath expression: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f" > <xsl:import href="../f/func-product.xsl"/> <xsl:output encoding="UTF-8" omit-xml-declaration="yes"/> <!-- This transformation should be applied to: testProduct.xml --> <xsl:template match="/"> <xsl:value-of select= "f:product(/*/*/*/*/(*[@sqlsource='newshares'] div *[@sqlsource='oldshares']))"/> </xsl:template> </xsl:stylesheet> When applied on the OP's source xml it produces the wanted result: 0.25 Here's the code for the f:product() function: func-product.xsl: ============ <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f xs" > <xsl:import href="func-foldl.xsl"/> <xsl:import href="../f/func-Operators.xsl"/> <xsl:function name="f:product"> <xsl:param name="pList"/> <xsl:sequence select="f:foldl(f:mult(), 1, $pList)"/> </xsl:function> </xsl:stylesheet> If someone loves writing expressions from scratch, they could substitute f:product() in the first transformation with the expression from the last transformation and they would still get a single XPath expression for the solution of the problem: f:foldl(f:mult(), 1, /*/*/*/*/(*[@sqlsource='newshares'] div *[@sqlsource='oldshares'])) ) Cheers, Dimitre Novatchev > > The alternative is to do a recursive scan of the values: write a template > (or XSLT 2.0 function) that takes a RECORDSECTION as an argument and the > product-so-far as a second argument. Compute the value above, multiply it by > the product-so-far, and call the template with the following-sibling > RECORDSECTION and the new product as the arguments. Start the thing off by > calling this template/function with the first RECORDSECTION and the value 1 > as arguments, terminate the recursion when there are no following siblings. > > Michael Kay > http://www.saxonica.com/ > > > > -----Original Message----- > > From: Whitney, Dan (CanWest Interactive) > > [mailto:DWhitney@xxxxxxxxxxx] > > Sent: 13 April 2005 13:58 > > To: 'mulberry - xsl' > > Subject: [xsl] params - keys? how to calculate product of > > parents with multiple children > > > > > > Hi am having trouble conceptualizing how/if I can calculate > > the following: > > I want to take the children of RECORDSECTION and divide > > attribute value > > newshares by attribute value oldshares. > > I then want to multiply the results of each those > > calculations (there may be > > 0 - any number of occurrences of RECORDSECTION). So for below > > it would be: > > (1/2)*(1/2)= 0.25 > > > > Any help/examples would be appreciated. > > > > Dan Whitney > > > > XML > > > > <?xml version="1.0" encoding="windows-1252"?> > > <?xml-stylesheet type="text/xsl" href="test/split_total.xsl"?> > > > > <PUBLICATION> > > <DOCUMENT source="splits" group="surveys" output="body"> > > <RECORD fragment="splits" recid="12129" fragid="13" product="surveys" > > group="surveys" status="1"><ID idtype="fpid">12129</ID> > > <RECORDSECTION docfragment="splits"> > > <RECORDITEM sqlsource="oldshares">2</RECORDITEM> > > <RECORDITEM sqlsource="newshares">1</RECORDITEM> > > </RECORDSECTION> > > <RECORDSECTION docfragment="splits"> > > <RECORDITEM sqlsource="oldshares">2</RECORDITEM> > > <RECORDITEM sqlsource="newshares">1</RECORDITEM> > > </RECORDSECTION> > > </RECORD> > > </DOCUMENT> > > </PUBLICATION> > > > > XSL > > > > <xsl:stylesheet > > version="1.0" > > xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> > > > > <xsl:output > > method="html" > > encoding="iso-8859-1" > > indent="yes" > > version="4.0"/> > > > > > > <xsl:template match="PUBLICATION"> > > <table border="0" cellpadding="2" cellspacing="2" > > width="410" cols="2" > > > <tr> > > <td> > > <xsl:for-each select="DOCUMENT/RECORD"> > > <!-- below would like to only define param once but have it > > increment based > > on position--> > > <xsl:variable name="product[position()]" > > select="RECORDSECTION[1]/RECORDITEM[@sqlsource='newshares'] div > > RECORDSECTION[1]/RECORDITEM[@sqlsource='oldshares']"/> > > <xsl:variable name="product[position()]" > > select="RECORDSECTION[2]/RECORDITEM[@sqlsource='newshares'] div > > RECORDSECTION[1]/RECORDITEM[@sqlsource='oldshares']"/> > > <!-- this was a half conceived attempt > > <xsl:for-each select="RECORDSECTION[1]"> > > <xsl:call-template name="splitfactor"> > > <xsl:with-param name="factor-subset" > > select="following-sibling::RECORDSECTION"/> > > </xsl:call-template>) > > </xsl:for-each> > > --> > > <!-- here don't even know how I would write this --> > > <xsl:value-of select="$product1 * $product2"/> > > </xsl:for-each> > > </td> > > </tr> > > </table> > > </xsl:template> > > > > <!-- half conceived attempt --> > > <xsl:template name="splitfactor"> > > <xsl:param name="factor-subset" select="1"/> > > <xsl:if test="$factor-subset[1]"> > > <xsl:call-template name="splitfactor"> > > <xsl:with-param name="factor-subset" > > select="$factor-subset[position() > > > 1]"/> > > </xsl:call-template> > > </xsl:if> > > </xsl:template> > > > > <xsl:template match="ID"/> > > > > </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] params - keys? how to cal, Michael Kay | Thread | RE: Re: [xsl] how to translate XML , cknell |
Re: [xsl] XSLT processor and substr, James Fuller | Date | RE: [xsl] Unusual Sort, Wendell Piez |
Month |