Project

Profile

Help

How to connect?
Download (11.2 KB) Statistics
| Branch: | Tag: | Revision:

he / latest10 / hej / net / sf / saxon / s9api / streams / package.html @ c74fd4aa

1
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
2
<!-- Copyright (c) 2018-2020 Saxonica Limited. -->
3
<!-- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -->
4
<!-- If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
5
<!-- This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. -->
6
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
7

    
8
<html>
9

    
10
<head>
11
    <title>Package overview for net.sf.saxon.s9api.streams</title>
12
</head>
13

    
14
<body>
15

    
16
<p>This package (introduced in Saxon 9.9) provides methods to manipulate XDM values using Java 8 streams.</p>
17

    
18
<p>A value in the XDM data model is represented by an instance of {@link net.sf.saxon.s9api.XdmValue}.
19
This is in general a sequence; the members of the sequence are instances of {@link net.sf.saxon.s9api.XdmItem}.
20
{@code XdmItem} is an abstract class; its concrete subclasses include {@link net.sf.saxon.s9api.XdmNode} for
21
nodes, {@link net.sf.saxon.s9api.XdmAtomicValue} for atomic values, {@link net.sf.saxon.s9api.XdmFunctionItem}
22
for function items, {@link net.sf.saxon.s9api.XdmMap} for maps, and {@link net.sf.saxon.s9api.XdmArray}
23
for arrays.</p>
24

    
25
<p>Given an <code>XdmNode</code> <code>N</code>, it is possible to select other nodes using an expression
26
such as <code>N.select(child("author")).asNode()</code>. The way this works is as follows:</p>
27

    
28
<ul>
29
    <li>The <code>select()</code> method (which applies to any <code>XdmValue</code>, not only
30
    an <code>XdmNode</code>) takes as its argument a {@link net.sf.saxon.s9api.streams.Step},
31
    and returns as its result an {@link net.sf.saxon.s9api.streams.XdmStream}. A <code>Step</code>
32
    is a function that takes an <code>XdmItem</code> as input, and returns a stream of items
33
    as its result; the <code>select()</code> method combines these streams into a single stream
34
    (in much the same way as the Java 8 <code>flatMap()</code> operation) and returns the result.</li>
35
    <li><code>child("author")</code> invokes a static method in class {@link net.sf.saxon.s9api.streams.Steps},
36
    which delivers a <code>Step</code> whose effect is to find the children of a supplied node that have
37
    local name <code>"author"</code>, returning these as a Stream. The <code>Steps</code> class provides
38
    a large collection of useful implementations of <code>Step</code>, including support for all the
39
    XPath axes (parent, child, descendant, following-sibling and so on).</li>
40
    <li>The class <code>XdmStream</code> (which will typically not be used explicitly) implements
41
    the standard Java 8 {@link java.util.streams.Stream} class; it does so by wrapping a standard
42
    Java 8 stream and delegating all standard methods to the wrapped stream. By subclassing the standard
43
    <code>Stream</code> interface, however, it is able to supply additional methods appropriate to
44
    streams of XDM items. For example, the <code>asNode()</code> example terminates the Stream pipeline
45
        by converting the result of the stream to a single <code>XdmNode</code> value (an unchecked
46
    exception occurs if the content of the stream is anything other than a single node).</li>
47
</ul>
48

    
49
<p>The power of the approach rests in the range of <code>Step</code> implementations available, and the way
50
these can be combined; and in the terminal operations to deliver the result of a stream in a useful way.
51
Although many standard implementations are available, these can be augmented with user-written methods;
52
since a {@code Step} is just a Java 8 {@code Function}, and an {@code XdmStream} is just a Java 8 {@code Stream},
53
all the standard Java 8 facilities for creating and combining functions and streams are available.</p>
54

    
55
<h2>Steps</h2>
56

    
57
<p>The steps that are available "off the shelf" from the {@link net.sf.saxon.s9api.streams.Steps}
58
class include the following:</p>
59

    
60
<ul>
61
    <li><p>For each of the 13 XPath axes, taking <code>child</code> as an example, four <code>Step</code>
62
        implementations are provided:</p>
63
        <ul>
64
            <li><code>child()</code> selects all the children of a node.</li>
65
            <li><code>child("lname")</code> selects all the children of a node that have the local name "lname".</li>
66
            <li><code>child("ns", "lname")</code> selects all the children of a node that have the namespace URI "ns"
67
                and local name "lname".</li>
68
            <li><code>child(predicate)</code> selects all the children of a node that satisfy the given predicate.
69
            The predicate may be any Java 8 {@link java.util.functions.Predicate}, but the class
70
                {@link net.sf.saxon.s9api.streams.Predicates} provides some off-the-shelf predicates that are
71
            particularly designed for navigating XDM information.</li>
72
        </ul>
73
    </li>
74
    <li><p>Two steps <code>S</code> and <code>T</code> may be combined into a single step using the <code>then</code>
75
    method: for example <code>child("X").then(attribute("A"))</code>.</p></li>
76
    <li><p>More generally, any sequence of steps may be combined using the <code>path()</code> function, for example
77
    <code>path(child("table"), child("thead"), child("trow"), attribute("class"))</code></p></li>
78
    <li><p>Where the steps in a path are the most commonly used variety, a path may be written using an abbreviated notation:
79
    <code>path("table", "thead", "trow", "@class")</code> is equivalent to the previous example.</p></li>
80
    <li><p>The results of two steps may also be concatenated: for example <code>child("author").cat(child("editor"))</code>
81
    concatenates the results of the two steps into a single stream.</p></li>
82
    <li><p>The <code>atomize()</code> step reduces nodes (and arrays) to atomic values, as defined in the XPath
83
    specification.</p></li>
84
    <li><p>If <code>S</code> is a <code>Step</code>, and <code>P</code> is a <code>Predicate</code>,
85
    then <code>S.where(P)</code> is also a <code>Step</code>, which selects those elements selected by
86
    <code>S</code> that satisfy <code>P</code>. For example <code>child().where(isElement())</code>
87
    selects those children of the starting node that are elements. (But this particular example can be
88
    written more easily as <code>child(isElement())</code>).</p></li>
89
</ul>
90

    
91
<h2>Predicates</h2>
92

    
93
<p>Predicates can be used either in the <code>where()</code> method to construct a new <code>Step</code>,
94
or they may be used in the standard Java 8 <code>filter()</code> method to filter the items in a stream.
95
Any predicate may be used in either context. The utility class {@link net.sf.saxon.s9api.streams.Predicates}
96
provides a range of predicates that are particularly suited to XDM navigation.</p>
97

    
98
<p>These predicates include:</p>
99

    
100
<ul>
101
    <li>Predicates <code>isNode()</code>, <code>isAtomicValue()</code>, <code>isMap()</code>, <code>isArray()</code>
102
    etc to test whether an <code>XdmItem</code> is a particular kind of item;</li>
103
    <li>Predicates <code>isElement()</code>, <code>isAttribute()</code>, <code>isText()</code>
104
    etc to test the kind of a node;</li>
105
    <li>The predicate <code>hasType()</code> to test whether an item matches a specific item type: for example
106
    <code>hasType(ItemType.XS_DATE_TIME)</code> tests whether it is an instance of <code>xs:dateTime</code>;</li>
107
    <li>The predicate <code>eq("string")</code> tests whether the string value of the item is equal
108
    to "string"</li>
109
    <li>The predicate <code>eq(XdmAtomicValue)</code> performs a typed comparison, for example comparing two
110
        values as numbers
111
    </li>
112
    <li>The predicate <code>matchesRegex("regex")</code> tests whether the string value of the item matches
113
    the regular expression "regex"</li>
114
    <li>If <code>S</code> is a <code>Step</code> and <code>P</code> is a <code>Predicate</code>, then
115
    <code>some(S, P)</code> is a predicate that returns true if some item returned by <code>S</code>
116
    satisfies <code>P</code>; similarly <code>every(S, P)</code> tests if all items returned by <code>S</code>
117
        satisfy <code>P</code>. For example <code>some(attribute("id"), eq("A123"))</code> is true for an element
118
    that has an <code>id</code> attribute equal to "A123". This particular condition can also be expressed
119
    more concisely as <code>eq(attribute("id"), "A123")</code></li>
120
</ul>
121

    
122
<h2>Operations on XDM streams</h2>
123

    
124
<p>An <code>XdmStream</code> (as delivered by <code>XdmValue.select(step)</code>) is an implementation of
125
a Java 8 Stream, so all the standard methods on <code>Stream</code> are available: for example <code>filter</code>,
126
<code>map()</code>, <code>flatMap</code>, <code>reduce</code>, <code>collect</code>. Where appropriate, these
127
are specialized to return an <code>XdmStream</code> rather than a generic <code>Stream</code>.</p>
128

    
129
<p><code>XdmStream</code> provides some additional terminal operations designed to make it convenient to convert
130
the contents of the stream into usable form. These include:</p>
131

    
132
<ul>
133
    <li><code>first()</code> - deliver the first item of the stream</li>
134
    <li><code>last()</code> - deliver the last item of the stream</li>
135
    <li><code>at()</code> - deliver the item at position N the stream</li>
136
    <li><code>exists()</code> - return true if the stream is non-empty</li>
137
    <li><code>subStream()</code> - deliver a stream containing a subsequence of the input stream</li>
138
    <li><code>asXdmValue()</code> - deliver the contents as an <code>XdmValue</code></li>
139
    <li><code>asList()</code> - deliver the contents as a <code>List&lt;XdmItem&gt;</code></li>
140
    <li><code>asListOfNodes()</code> - deliver the contents as a <code>List&lt;XdmNode&gt;</code></li>
141
    <li><code>asOptionalNode()</code> - deliver the contents as an <code>Optional&lt;XdmNode&gt;</code></li>
142
    <li><code>asNode()</code> - deliver the contents as a single <code>XdmNode</code></li>
143
    <li><code>asListOfAtomic()</code> - deliver the contents as a <code>List&lt;XdmAtomicValue&gt;</code></li>
144
    <li><code>asOptionalAtomic()</code> - deliver the contents as an <code>Optional&lt;XdmAtomicValue&gt;</code></li>
145
    <li><code>asAtomic()</code> - deliver the contents as a single <code>XdmAtomicValue</code></li>
146
    <li><code>asOptionalString()</code> - deliver the contents as an <code>Optional&lt;String&gt;</code> by taking
147
    the string value of each item</li>
148
    <li><code>asString()</code> - deliver the contents as a single <code>String</code></li>
149
</ul>
150

    
151
<p>The choice of terminal operation determines the return type (for example <code>asOptionalNode()</code>
152
returns <code>Optional&lt;XdmNode>)</code>, and also causes a run-time check that the value actually
153
conforms to these expectations. For example, if <code>asNode()</code> is used, then an unchecked exception
154
occurs if the sequence has a length other than 1 (one), or if its single item is not a node.</p>
155

    
156
<p>Other ways of generating an <code>XdmStream</code> include:</p>
157

    
158
<ul>
159
    <li>As the result of an XPath expression, using the method <code>XPathSelector.stream()</code></li>
160
    <li>As the result of an XQuery expression, using the method <code>XQueryEvaluator.stream()</code></li>
161
    <li>As the result of <code>XdmSequenceIterator.stream()</code></li>
162
</ul>
163

    
164
<hr>
165

    
166
</body>
167
</html>
(7-7/7)