Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > Calculations inside XPath expressions?

Reply
Thread Tools

Calculations inside XPath expressions?

 
 
Christofer Dutz
Guest
Posts: n/a
 
      04-10-2005
Hi,

I just ran into an interesting situation, where I was not able to write
an xpath expression doing what I want it to. Mabe someone here can help
me ... I hope

Here a sample xml-file I want to do the query on:
<?xml version="1.0" encoding="UTF-8"?>
<cart>
<product count="2" price="10.00" id="sdkjfhdaf-A"/>
<product count="1" price="10.00" id="sdkjfhdaf-A"/>
<product count="1" price="30.00" id="sdkjfhdaf-B"/>
<product count="4" price="12.50" id="sdkjfhdaf-C"/>
<product count="2" price="16.00" id="sdkjfhdaf-A"/>
<product count="3" price="119.00" id="sdkjfhdaf-C"/>
<product count="2" price="13.99" id="sdkjfhdaf-A"/>
<product count="10" price="12.34" id="sdkjfhdaf-B"/>
<product count="3" price="11.00" id="sdkjfhdaf-B"/>
<product count="1" price="1.00" id="sdkjfhdaf-A"/>
</cart>

I would like to test, if the total price for all products in the cart
which have an Id containing "-C" in their id-attribute is biger than
lets say 100.
I have no problem selecting either the price or count attribute of these
but I am unable to get "price * count".
Any suggestions?

I created a workaround by adding an additional total-attribute and
everything is working fine, it's just my scientiffic curiosity

Chris
 
Reply With Quote
 
 
 
 
Martin Honnen
Guest
Posts: n/a
 
      04-10-2005


Christofer Dutz wrote:


> Here a sample xml-file I want to do the query on:
> <?xml version="1.0" encoding="UTF-8"?>
> <cart>
> <product count="2" price="10.00" id="sdkjfhdaf-A"/>
> <product count="1" price="10.00" id="sdkjfhdaf-A"/>
> <product count="1" price="30.00" id="sdkjfhdaf-B"/>
> <product count="4" price="12.50" id="sdkjfhdaf-C"/>
> <product count="2" price="16.00" id="sdkjfhdaf-A"/>
> <product count="3" price="119.00" id="sdkjfhdaf-C"/>
> <product count="2" price="13.99" id="sdkjfhdaf-A"/>
> <product count="10" price="12.34" id="sdkjfhdaf-B"/>
> <product count="3" price="11.00" id="sdkjfhdaf-B"/>
> <product count="1" price="1.00" id="sdkjfhdaf-A"/>
> </cart>
>
> I would like to test, if the total price for all products in the cart
> which have an Id containing "-C" in their id-attribute is biger than
> lets say 100.
> I have no problem selecting either the price or count attribute of these
> but I am unable to get "price * count".
> Any suggestions?


XPath (at least version 1.0) alone can't do that, you need an XSLT 1.0
stylesheet with a template that adds up the values as necessary:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xslutput method="xml" indent="yes" />

<xslaram name="matchSubstring" select="'-C'" />

<xsl:template match="/">
<results>
<xsl:call-template name="getTotal">
<xsl:with-param name="products"
select="cart/product[contains(@id, $matchSubstring)]" />
</xsl:call-template>
</results>
</xsl:template>

<xsl:template name="getTotal">
<xslaram name="products" />
<xslaram name="currentTotal" select="0" />
<xsl:variable name="currentProduct" select="$products[1]" />
<xsl:choose>
<xsl:when test="not($currentProduct)">
<total>
<xsl:value-of select="$currentTotal" />
</total>
</xsl:when>
<xsltherwise>
<xsl:call-template name="getTotal">
<xsl:with-param name="products" select="$products[position()
&gt; 1]" />
<xsl:with-param name="currentTotal" select="$currentTotal +
$currentProduct/@count * $currentProduct/@price" />
</xsl:call-template>
</xsltherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

--

Martin Honnen
http://JavaScript.FAQTs.com/
 
Reply With Quote
 
 
 
 
Christofer Dutz
Guest
Posts: n/a
 
      04-10-2005
Hmmm ... I hoped to get a different answer ... well that might be the
reason why I was not able to do it
What about newer XPath Versions?
Adding an XSL transformation to this would be some kind of overkill ...
as I said, was just curiosity.

Thanks anyway,
Chris

Martin Honnen wrote:

> XPath (at least version 1.0) alone can't do that, you need an XSLT 1.0
> stylesheet with a template that adds up the values as necessary:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet
> xmlnssl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xslutput method="xml" indent="yes" />
>
> <xslaram name="matchSubstring" select="'-C'" />
>
> <xsl:template match="/">
> <results>
> <xsl:call-template name="getTotal">
> <xsl:with-param name="products" select="cart/product[contains(@id,
> $matchSubstring)]" />
> </xsl:call-template>
> </results>
> </xsl:template>
>
> <xsl:template name="getTotal">
> <xslaram name="products" />
> <xslaram name="currentTotal" select="0" />
> <xsl:variable name="currentProduct" select="$products[1]" />
> <xsl:choose>
> <xsl:when test="not($currentProduct)">
> <total>
> <xsl:value-of select="$currentTotal" />
> </total>
> </xsl:when>
> <xsltherwise>
> <xsl:call-template name="getTotal">
> <xsl:with-param name="products" select="$products[position()
> &gt; 1]" />
> <xsl:with-param name="currentTotal" select="$currentTotal +
> $currentProduct/@count * $currentProduct/@price" />
> </xsl:call-template>
> </xsltherwise>
> </xsl:choose>
> </xsl:template>
>
> </xsl:stylesheet>
>

 
Reply With Quote
 
=?ISO-8859-1?Q?J=FCrgen_Kahrs?=
Guest
Posts: n/a
 
      04-10-2005
Christofer Dutz wrote:

> Hmmm ... I hoped to get a different answer ... well that might be the
> reason why I was not able to do it
> What about newer XPath Versions?


Are you really sure you need XPath ?

> Adding an XSL transformation to this would be some kind of overkill ...
> as I said, was just curiosity.


There are other solutions. Even simple ones.
If other tools are acceptable to you,
I promise to supply a solution (in XMLgawk).
 
Reply With Quote
 
Martin Honnen
Guest
Posts: n/a
 
      04-10-2005


Christofer Dutz wrote:


> What about newer XPath Versions?


With XPath 2.0 you could do it with a single expression, using the sum
function on the result returned from a for..in expression:
sum(for $product in /cart/product[contains(@id, $matchSubstring)]
return $product/@count * $product/@price)

Saxon 8 implements XPath 2.0 while the spec is being developed:
<http://saxon.sourceforge.net/#F8.4SA>


--

Martin Honnen
http://JavaScript.FAQTs.com/
 
Reply With Quote
 
 
 
Reply

Thread Tools

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
"Memory leak" in javax.xml.xpath.XPath Marvin_123456 Java 4 07-29-2005 03:49 PM
XPath: efficiency in xpath expressions Tjerk Wolterink XML 1 11-13-2004 06:03 PM
Are there any XPath parsers that generate XPath trees? goog XML 0 01-14-2004 01:47 PM
XPath that does not include other XPath Anna XML 0 07-31-2003 07:55 AM
Problem selecting a node with XPATH if attribute value contains backslashes - how to force XPATH string to be treated as literal? Alastair Cameron XML 1 07-08-2003 07:24 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57