Project

Profile

Help

Looking for a way of iterating over an XPath sequence that itself contains sequences in 9.1.0.8 Saxonica Basic

Added by Alan Painter about 10 years ago

Hello,

Using Saxonica 9.1.0.8 (admittedly oldish), I have an XPath expression that looks like:


for $ab in /A/B return ($ab/C[1], $ab/C[2])

An example input document for this would be:



  
    1
    2
  
  
    3
    4
  

From the XPathSelector, I'd like to be able to retrieve this as an iterator on a outer sequence of size two, each element of the outer sequence itself containing an inner sequence of two elements, as in:


(1,2)
(3,4)

But I haven't found the magic incantation for this and I'm beginning to wonder if it simply isn't possible, that sequences of sequences are simply coalesced into bigger sequences.

Is there any way of retrieving as above?

Adding some standalone code as an example:


import net.sf.saxon.s9api.*;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import java.io.ByteArrayInputStream;
import java.util.Iterator;

public class XPathStandaloneTestCase_1 {

    private final Processor processor = new Processor(false);
    private final XPathCompiler compiler  = processor.newXPathCompiler();

    public static void main(String[] args) throws SaxonApiException {
        new XPathStandaloneTestCase_1();
    }

    public XPathStandaloneTestCase_1() throws SaxonApiException {
        final XPathExecutable xpathExecutable = tryToCompile("for $ab in /A/B return ($ab/C[1], $ab/C[2])");
        final XPathSelector xpathSelector = xpathExecutable.load();
        xpathSelector.setContextItem(makeDocumentNode("" +
                                                        "" +
                                                          "1" +
                                                          "2" +
                                                        "" +
                                                        "" +
                                                          "3" +
                                                          "4" +
                                                        "" +
                                                      ""));

        System.out.println("trying with XPathSelector iterator");
        for (final XdmValue valueInSequence: xpathSelector) {
            printSequence(valueInSequence);
        }

        System.out.println("trying with evaluate()");
        for (final XdmValue valueInSequence: xpathSelector.evaluate()) {
            printSequence(valueInSequence);
        }
    }

    private XdmNode makeDocumentNode(String input) throws SaxonApiException {
        final Source inputSource   = new StreamSource(new ByteArrayInputStream(input.getBytes()));
        return processor.newDocumentBuilder().build(inputSource);
    }

    private void printSequence(XdmValue valueInSequence) {
        System.out.print  ("(");
        final Iterator iterator = valueInSequence.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next().getStringValue());
            if (iterator.hasNext()) {
                System.out.print(",");
            }
        }
        System.out.println(")");
    }

    private XPathExecutable tryToCompile(String toCompile) {
        try {
            return compiler.compile(toCompile);
        } catch (Exception e) {
            System.out.println("Could not compile the expression.  Shutting down.");
            System.exit(0);
        }
        return null;
    }
}

This produces output as:


trying with XPathSelector iterator
(1)
(2)
(3)
(4)
trying with evaluate()
(1)
(2)
(3)
(4)

Thanks for any pointers or cogent arguments for disabusing me of my illusions.

-alan


Replies (2)

RE: Looking for a way of iterating over an XPath sequence that itself contains sequences in 9.1.0.8 Saxonica Basic - Added by Michael Kay about 10 years ago

There's no such thing as a sequence of sequences in the XPath 2.0 data model; the result of your XPath expression is a flat sequence (as you suspect).

You could try solving this with maps:

map:new( /A/B ! map:entry (position(), ($ab/C[1]/data(), $ab/C[2]/data()))

which will return

map{ 1: (1,2), 2:(3,4) }

But I'm not sure that the s9api interface makes a returned map particularly easy to process from the Java level.

RE: Looking for a way of iterating over an XPath sequence that itself contains sequences in 9.1.0.8 Saxonica Basic - Added by Alan Painter about 10 years ago

Dr Kay,

Thanks very much for the confirmation.

Maps looks like the right solution except for the more recent versions but doesn't quite seem to work from within 9.1 which is no doubt too old and pre-dates the map extensions.

I'll find a different, not necessarily elegant, way of doing this within my current operating constraints.

Clearly maps is the future direction of so many languages.

thanks and very best regards

-alan

    (1-2/2)

    Please register to reply