Buck
Buck

Reputation: 327

XQuery method, trying to sum values read from xml

I'm pretty new to XQuery and I'm trying to write an example function that I can't get to work. I want to read an xml file, parse out the "time" values, sum them as they're read and return the sum. This is trivial and I'm looking to build more functionality into it but I'd like to get this working first. Also, I know there's a "sum" directive in XQuery that would do just this but I want to add more to it so the built-in sum is insufficient for my needs.

Here's my function:

bool
example(Zorba* aZorba)
{
   XQuery_t lQuery = aZorba->compileQuery(
                        "for $i in fn:doc('/tmp/products.xml')//time"
                         "let $sum := xs:integer($i)"
                                 " return $sum"
);

  DynamicContext* lCtx = lQuery->getDynamicContext();

  lCtx->setContextItemAsDocument("temp_measurements.xml", lDocStream);

  try {
    std::cout << lQuery << std::endl;
  } catch (DynamicException& e) {
    std::cerr << e.getDescription() << std::endl;
    return false;
  } catch (StaticException& f){
        std::cerr << f.getDescription() << f.getErrorCodeAsString(f.getErrorCode()) << std::endl;
        return false;
  }
}

It's called with an appropriate main(). If I comment out the line that starts "let $sum..." then this works in that it returns the time values as a series of integers like this: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3....

Input file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<temps>
  <temp>
    <time>0</time>
    <lat>0</lat>
    <long>0</long>
    <value>0</value>
  </temp>
  <temp>
    <time>1</time>
    <lat>0</lat>
    <long>1</long>
    <value>0</value>
  </temp>
 ...

Upvotes: 0

Views: 2574

Answers (2)

Bill
Bill

Reputation: 26

its looks like you want to use fn:sum

like this:

fn:sum(
    (
        1, 1, 1, 1, 0, 0, 1, 0
    ), 
    0
)

More information here: http://www.xqueryfunctions.com/xq/fn_sum.html

Upvotes: 1

Dave Cassel
Dave Cassel

Reputation: 8422

I'm a relative newcomer to XQuery myself, but one of the things I was surprised about was the lack of a map() function, as in LISP, to take a sequence of values and combine them into one, passing in the combining function. In LISP, I think you'd want something like "(map '+ (0 0 0 1 1 2 2 3 1 2))". You can do something similar in XQuery, but you have to write it yourself:

declare function local:sum-times($seq)
{
  if (count($seq) < 2)
  then
    subsequence($seq, 1, 1)
  else
    subsequence($seq, 1, 1) + local:sum-times(subsequence($seq, 2))
};

So then you can write "local:sum-times(for $i in fn:doc()...)". Basically, this recreates the sum() function you mentioned, but now you can make the changes you need.

Upvotes: 0

Related Questions