[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: Count a substring of an attribute in childnodes

Subject: RE: Count a substring of an attribute in childnodes
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 9 Mar 2005 14:02:58 -0000
xpath substring attribute
> I tried 
> select="sum(number(colspec[contains(@colwidth,'*')]/substring-
> before(@colwidth,'*')))" 
> instead, but this does not work either. 

The number() function returns a single number. Summing over a single number
obviously isn't going to do any good. You're thrashing around rather than
thinking about the problem clearly.

Your problem has the general form:

1) select a set of nodes
2) for each node, compute a number
3) find the sum of the numbers

This is often referred to as the "sum of price times quantity" problem,
though in your case the computation in step 2 is slightly different. Let's
solve the general problem by saying that in step 2, we want to call a
function f(node)->number. Having got a general solution, it's then easy to
apply it to your case and to many other similar cases just by changing the
function f.

In XPath 2.0 the solution can be written

  sum(for $n in $nodes return f($n))

or more concisely

  sum($nodes/f(.))

You've been offered two solutions for XSLT/XPath 1.0, and I'll add a third.

The first solution is recursion. Cutting out the XSLT noise, the solution
can be expressed:

total($nodes):
choose
 when count($nodes)=0
   return 0 
 otherwise
   return f($nodes[1]) + total($nodes[position()>1])

The second solution is Dimitre's functional programming approach. This is
the one that's closest to the way I expressed the problem above. Note that I
described a three-stage approach in which stage 2 involves computing some
function. This is a classic higher-order function. The three-step algorithm
is a function that takes two arguments: the sequence of nodes, and the
function to be computed in step 2. Dimitre's FXSL library allows you to
write the solution in this form. It takes some getting used to, but it's the
most economical way of solving the problem; and although it involves calling
the FXSL library, that's written in pure XSLT 1.0 so it should be completely
portable.

The third solution uses the pipeline design pattern mentioned in my mail
earlier today. Here you do the job in two steps. The output of the first
step is a tree in which the elements carry an attribute that's the computed
number (the value of f(node)). The second step uses the sum() function to
sum over these attributes. 

Michael Kay
http://www.saxonica.com/

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.