mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-17 22:42:25 +02:00
doc: Add SXPath documentation from sources
Fixes <http://bugs.gnu.org/19478>. * doc/ref/sxml.texi (SXPath): Add procedure documentation from sources. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
parent
3bda6eb9df
commit
fbe95dc6e6
1 changed files with 267 additions and 35 deletions
|
@ -3,6 +3,10 @@
|
||||||
@c Copyright (C) 2013 Free Software Foundation, Inc.
|
@c Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
@c See the file guile.texi for copying conditions.
|
@c See the file guile.texi for copying conditions.
|
||||||
|
|
||||||
|
@c SXPath documentation based on SXPath.scm by Oleg Kiselyov,
|
||||||
|
@c which is in the public domain according to <http://okmij.org/ftp/>
|
||||||
|
@c and <http://ssax.sourceforge.net/>.
|
||||||
|
|
||||||
@node SXML
|
@node SXML
|
||||||
@section SXML
|
@section SXML
|
||||||
|
|
||||||
|
@ -250,8 +254,8 @@ internal and external parsed entities, user-controlled handling of
|
||||||
whitespace, and validation. This module therefore is intended to be a
|
whitespace, and validation. This module therefore is intended to be a
|
||||||
framework, a set of ``Lego blocks'' you can use to build a parser
|
framework, a set of ``Lego blocks'' you can use to build a parser
|
||||||
following any discipline and performing validation to any degree. As an
|
following any discipline and performing validation to any degree. As an
|
||||||
example of the parser construction, this file includes a semi-validating
|
example of the parser construction, the source file includes a
|
||||||
SXML parser.
|
semi-validating SXML parser.
|
||||||
|
|
||||||
SSAX has a ``sequential'' feel of SAX yet a ``functional style'' of DOM.
|
SSAX has a ``sequential'' feel of SAX yet a ``functional style'' of DOM.
|
||||||
Like a SAX parser, the framework scans the document only once and
|
Like a SAX parser, the framework scans the document only once and
|
||||||
|
@ -725,95 +729,323 @@ location path is a relative path applied to the root node.
|
||||||
Similarly to XPath, SXPath defines full and abbreviated notations for
|
Similarly to XPath, SXPath defines full and abbreviated notations for
|
||||||
location paths. In both cases, the abbreviated notation can be
|
location paths. In both cases, the abbreviated notation can be
|
||||||
mechanically expanded into the full form by simple rewriting rules. In
|
mechanically expanded into the full form by simple rewriting rules. In
|
||||||
case of SXPath the corresponding rules are given as comments to a sxpath
|
the case of SXPath the corresponding rules are given in the
|
||||||
function, below. The regression test suite at the end of this file shows
|
documentation of the @code{sxpath} procedure.
|
||||||
a representative sample of SXPaths in both notations, juxtaposed with
|
@xref{sxpath-procedure-docs,,SXPath procedure documentation}.
|
||||||
the corresponding XPath expressions. Most of the samples are borrowed
|
|
||||||
literally from the XPath specification, while the others are adjusted
|
The regression test suite at the end of the file @file{SXPATH-old.scm}
|
||||||
for our running example, tree1.
|
shows a representative sample of SXPaths in both notations, juxtaposed
|
||||||
|
with the corresponding XPath expressions. Most of the samples are
|
||||||
|
borrowed literally from the XPath specification.
|
||||||
|
|
||||||
|
Much of the following material is taken from the SXPath sources by Oleg
|
||||||
|
Kiselyov et al.
|
||||||
|
|
||||||
|
@subsubsection Basic Converters and Applicators
|
||||||
|
|
||||||
|
A converter is a function mapping a nodeset (or a single node) to another
|
||||||
|
nodeset. Its type can be represented like this:
|
||||||
|
|
||||||
|
@example
|
||||||
|
type Converter = Node|Nodeset -> Nodeset
|
||||||
|
@end example
|
||||||
|
|
||||||
|
A converter can also play the role of a predicate: in that case, if a
|
||||||
|
converter, applied to a node or a nodeset, yields a non-empty nodeset,
|
||||||
|
the converter-predicate is deemed satisfied. Likewise, an empty nodeset
|
||||||
|
is equivalent to @code{#f} in denoting failure.
|
||||||
|
|
||||||
@subsubsection Usage
|
|
||||||
@deffn {Scheme Procedure} nodeset? x
|
@deffn {Scheme Procedure} nodeset? x
|
||||||
|
Return @code{#t} if @var{x} is a nodeset.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-typeof? crit
|
@deffn {Scheme Procedure} node-typeof? crit
|
||||||
|
This function implements a 'Node test' as defined in Sec. 2.3 of the
|
||||||
|
XPath document. A node test is one of the components of a location
|
||||||
|
step. It is also a converter-predicate in SXPath.
|
||||||
|
|
||||||
|
The function @code{node-typeof?} takes a type criterion and returns a
|
||||||
|
function, which, when applied to a node, will tell if the node satisfies
|
||||||
|
the test.
|
||||||
|
|
||||||
|
The criterion @var{crit} is a symbol, one of the following:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item id
|
||||||
|
tests if the node has the right name (id)
|
||||||
|
|
||||||
|
@item @@
|
||||||
|
tests if the node is an <attributes-coll>
|
||||||
|
|
||||||
|
@item *
|
||||||
|
tests if the node is an <Element>
|
||||||
|
|
||||||
|
@item *text*
|
||||||
|
tests if the node is a text node
|
||||||
|
|
||||||
|
@item *PI*
|
||||||
|
tests if the node is a PI (processing instruction) node
|
||||||
|
|
||||||
|
@item *any*
|
||||||
|
@code{#t} for any type of node
|
||||||
|
@end table
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-eq? other
|
@deffn {Scheme Procedure} node-eq? other
|
||||||
|
A curried equivalence converter predicate that takes a node @var{other}
|
||||||
|
and returns a function that takes another node. The two nodes are
|
||||||
|
compared using @code{eq?}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-equal? other
|
@deffn {Scheme Procedure} node-equal? other
|
||||||
|
A curried equivalence converter predicate that takes a node @var{other}
|
||||||
|
and returns a function that takes another node. The two nodes are
|
||||||
|
compared using @code{equal?}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-pos n
|
@deffn {Scheme Procedure} node-pos n
|
||||||
|
Select the @var{n}'th element of a nodeset and return as a singular
|
||||||
|
nodeset. If the @var{n}'th element does not exist, return an empty
|
||||||
|
nodeset. If @var{n} is a negative number the node is picked from the
|
||||||
|
tail of the list.
|
||||||
|
|
||||||
|
@example
|
||||||
|
((node-pos 1) nodeset) ; return the the head of the nodeset (if exists)
|
||||||
|
((node-pos 2) nodeset) ; return the node after that (if exists)
|
||||||
|
((node-pos -1) nodeset) ; selects the last node of a non-empty nodeset
|
||||||
|
((node-pos -2) nodeset) ; selects the last but one node, if exists.
|
||||||
|
@end example
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} filter pred?
|
@deffn {Scheme Procedure} filter pred?
|
||||||
@verbatim
|
A filter applicator, which introduces a filtering context. The argument
|
||||||
-- Scheme Procedure: filter pred list
|
converter @var{pred?} is considered a predicate, with either @code{#f}
|
||||||
Return all the elements of 2nd arg LIST that satisfy predicate
|
or @code{nil} meaning failure.
|
||||||
PRED. The list is not disordered - elements that appear in the
|
|
||||||
result list occur in the same order as they occur in the argument
|
|
||||||
list. The returned list may share a common tail with the argument
|
|
||||||
list. The dynamic order in which the various applications of pred
|
|
||||||
are made is not specified.
|
|
||||||
|
|
||||||
(filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4)
|
|
||||||
|
|
||||||
|
|
||||||
@end verbatim
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} take-until pred?
|
@deffn {Scheme Procedure} take-until pred?
|
||||||
|
@example
|
||||||
|
take-until:: Converter -> Converter, or
|
||||||
|
take-until:: Pred -> Node|Nodeset -> Nodeset
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Given a converter-predicate @var{pred?} and a nodeset, apply the
|
||||||
|
predicate to each element of the nodeset, until the predicate yields
|
||||||
|
anything but @code{#f} or @code{nil}. Return the elements of the input
|
||||||
|
nodeset that have been processed until that moment (that is, which fail
|
||||||
|
the predicate).
|
||||||
|
|
||||||
|
@code{take-until} is a variation of the @code{filter} above:
|
||||||
|
@code{take-until} passes elements of an ordered input set up to (but not
|
||||||
|
including) the first element that satisfies the predicate. The nodeset
|
||||||
|
returned by @code{((take-until (not pred)) nset)} is a subset -- to be
|
||||||
|
more precise, a prefix -- of the nodeset returned by @code{((filter
|
||||||
|
pred) nset)}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} take-after pred?
|
@deffn {Scheme Procedure} take-after pred?
|
||||||
|
@example
|
||||||
|
take-after:: Converter -> Converter, or
|
||||||
|
take-after:: Pred -> Node|Nodeset -> Nodeset
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Given a converter-predicate @var{pred?} and a nodeset, apply the
|
||||||
|
predicate to each element of the nodeset, until the predicate yields
|
||||||
|
anything but @code{#f} or @code{nil}. Return the elements of the input
|
||||||
|
nodeset that have not been processed: that is, return the elements of
|
||||||
|
the input nodeset that follow the first element that satisfied the
|
||||||
|
predicate.
|
||||||
|
|
||||||
|
@code{take-after} along with @code{take-until} partition an input
|
||||||
|
nodeset into three parts: the first element that satisfies a predicate,
|
||||||
|
all preceding elements and all following elements.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} map-union proc lst
|
@deffn {Scheme Procedure} map-union proc lst
|
||||||
|
Apply @var{proc} to each element of @var{lst} and return the list of results.
|
||||||
|
If @var{proc} returns a nodeset, splice it into the result
|
||||||
|
|
||||||
|
From another point of view, @code{map-union} is a function
|
||||||
|
@code{Converter->Converter}, which places an argument-converter in a joining
|
||||||
|
context.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-reverse node-or-nodeset
|
@deffn {Scheme Procedure} node-reverse node-or-nodeset
|
||||||
|
@example
|
||||||
|
node-reverse :: Converter, or
|
||||||
|
node-reverse:: Node|Nodeset -> Nodeset
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Reverses the order of nodes in the nodeset. This basic converter is
|
||||||
|
needed to implement a reverse document order (see the XPath
|
||||||
|
Recommendation).
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-trace title
|
@deffn {Scheme Procedure} node-trace title
|
||||||
|
@example
|
||||||
|
node-trace:: String -> Converter
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@code{(node-trace title)} is an identity converter. In addition it
|
||||||
|
prints out the node or nodeset it is applied to, prefixed with the
|
||||||
|
@var{title}. This converter is very useful for debugging.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@subsubsection Converter Combinators
|
||||||
|
|
||||||
|
Combinators are higher-order functions that transmogrify a converter or
|
||||||
|
glue a sequence of converters into a single, non-trivial converter. The
|
||||||
|
goal is to arrive at converters that correspond to XPath location paths.
|
||||||
|
|
||||||
|
From a different point of view, a combinator is a fixed, named
|
||||||
|
@dfn{pattern} of applying converters. Given below is a complete set of
|
||||||
|
such patterns that together implement XPath location path specification.
|
||||||
|
As it turns out, all these combinators can be built from a small number
|
||||||
|
of basic blocks: regular functional composition, @code{map-union} and
|
||||||
|
@code{filter} applicators, and the nodeset union.
|
||||||
|
|
||||||
@deffn {Scheme Procedure} select-kids test-pred?
|
@deffn {Scheme Procedure} select-kids test-pred?
|
||||||
|
@code{select-kids} takes a converter (or a predicate) as an argument and
|
||||||
|
returns another converter. The resulting converter applied to a nodeset
|
||||||
|
returns an ordered subset of its children that satisfy the predicate
|
||||||
|
@var{test-pred?}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-self pred?
|
@deffn {Scheme Procedure} node-self pred?
|
||||||
@verbatim
|
Similar to @code{select-kids} except that the predicate @var{pred?} is
|
||||||
-- Scheme Procedure: filter pred list
|
applied to the node itself rather than to its children. The resulting
|
||||||
Return all the elements of 2nd arg LIST that satisfy predicate
|
nodeset will contain either one component, or will be empty if the node
|
||||||
PRED. The list is not disordered - elements that appear in the
|
failed the predicate.
|
||||||
result list occur in the same order as they occur in the argument
|
|
||||||
list. The returned list may share a common tail with the argument
|
|
||||||
list. The dynamic order in which the various applications of pred
|
|
||||||
are made is not specified.
|
|
||||||
|
|
||||||
(filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4)
|
|
||||||
|
|
||||||
|
|
||||||
@end verbatim
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-join . selectors
|
@deffn {Scheme Procedure} node-join . selectors
|
||||||
|
@example
|
||||||
|
node-join:: [LocPath] -> Node|Nodeset -> Nodeset, or
|
||||||
|
node-join:: [Converter] -> Converter
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Join the sequence of location steps or paths as described above.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-reduce . converters
|
@deffn {Scheme Procedure} node-reduce . converters
|
||||||
|
@example
|
||||||
|
node-reduce:: [LocPath] -> Node|Nodeset -> Nodeset, or
|
||||||
|
node-reduce:: [Converter] -> Converter
|
||||||
|
@end example
|
||||||
|
|
||||||
|
A regular functional composition of converters. From a different point
|
||||||
|
of view, @code{((apply node-reduce converters) nodeset)} is equivalent
|
||||||
|
to @code{(foldl apply nodeset converters)}, i.e., folding, or reducing,
|
||||||
|
a list of converters with the nodeset as a seed.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-or . converters
|
@deffn {Scheme Procedure} node-or . converters
|
||||||
|
@example
|
||||||
|
node-or:: [Converter] -> Converter
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This combinator applies all converters to a given node and produces the
|
||||||
|
union of their results. This combinator corresponds to a union
|
||||||
|
(@code{|} operation) for XPath location paths.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-closure test-pred?
|
@deffn {Scheme Procedure} node-closure test-pred?
|
||||||
|
@example
|
||||||
|
node-closure:: Converter -> Converter
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Select all @emph{descendants} of a node that satisfy a
|
||||||
|
converter-predicate @var{test-pred?}. This combinator is similar to
|
||||||
|
@code{select-kids} but applies to grand... children as well. This
|
||||||
|
combinator implements the @code{descendant::} XPath axis. Conceptually,
|
||||||
|
this combinator can be expressed as
|
||||||
|
|
||||||
|
@example
|
||||||
|
(define (node-closure f)
|
||||||
|
(node-or
|
||||||
|
(select-kids f)
|
||||||
|
(node-reduce (select-kids (node-typeof? '*)) (node-closure f))))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This definition, as written, looks somewhat like a fixpoint, and it will
|
||||||
|
run forever. It is obvious however that sooner or later
|
||||||
|
@code{(select-kids (node-typeof? '*))} will return an empty nodeset. At
|
||||||
|
this point further iterations will no longer affect the result and can
|
||||||
|
be stopped.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} node-parent rootnode
|
@deffn {Scheme Procedure} node-parent rootnode
|
||||||
|
@example
|
||||||
|
node-parent:: RootNode -> Converter
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@code{(node-parent rootnode)} yields a converter that returns a parent
|
||||||
|
of a node it is applied to. If applied to a nodeset, it returns the
|
||||||
|
list of parents of nodes in the nodeset. The @var{rootnode} does not
|
||||||
|
have to be the root node of the whole SXML tree -- it may be a root node
|
||||||
|
of a branch of interest.
|
||||||
|
|
||||||
|
Given the notation of Philip Wadler's paper on semantics of XSLT,
|
||||||
|
|
||||||
|
@verbatim
|
||||||
|
parent(x) = { y | y=subnode*(root), x=subnode(y) }
|
||||||
|
@end verbatim
|
||||||
|
|
||||||
|
Therefore, @code{node-parent} is not the fundamental converter: it can
|
||||||
|
be expressed through the existing ones. Yet @code{node-parent} is a
|
||||||
|
rather convenient converter. It corresponds to a @code{parent::} axis
|
||||||
|
of SXPath. Note that the @code{parent::} axis can be used with an
|
||||||
|
attribute node as well.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@anchor{sxpath-procedure-docs}
|
||||||
@deffn {Scheme Procedure} sxpath path
|
@deffn {Scheme Procedure} sxpath path
|
||||||
|
Evaluate an abbreviated SXPath.
|
||||||
|
|
||||||
|
@example
|
||||||
|
sxpath:: AbbrPath -> Converter, or
|
||||||
|
sxpath:: AbbrPath -> Node|Nodeset -> Nodeset
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@var{path} is a list. It is translated to the full SXPath according to
|
||||||
|
the following rewriting rules:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(sxpath '())
|
||||||
|
@result{} (node-join)
|
||||||
|
|
||||||
|
(sxpath '(path-component ...))
|
||||||
|
@result{} (node-join (sxpath1 path-component) (sxpath '(...)))
|
||||||
|
|
||||||
|
(sxpath1 '//)
|
||||||
|
@result{} (node-or
|
||||||
|
(node-self (node-typeof? '*any*))
|
||||||
|
(node-closure (node-typeof? '*any*)))
|
||||||
|
|
||||||
|
(sxpath1 '(equal? x))
|
||||||
|
@result{} (select-kids (node-equal? x))
|
||||||
|
|
||||||
|
(sxpath1 '(eq? x))
|
||||||
|
@result{} (select-kids (node-eq? x))
|
||||||
|
|
||||||
|
(sxpath1 ?symbol)
|
||||||
|
@result{} (select-kids (node-typeof? ?symbol)
|
||||||
|
|
||||||
|
(sxpath1 procedure)
|
||||||
|
@result{} procedure
|
||||||
|
|
||||||
|
(sxpath1 '(?symbol ...))
|
||||||
|
@result{} (sxpath1 '((?symbol) ...))
|
||||||
|
|
||||||
|
(sxpath1 '(path reducer ...))
|
||||||
|
@result{} (node-reduce (sxpath path) (sxpathr reducer) ...)
|
||||||
|
|
||||||
|
(sxpathr number)
|
||||||
|
@result{} (node-pos number)
|
||||||
|
|
||||||
|
(sxpathr path-filter)
|
||||||
|
@result{} (filter (sxpath path-filter))
|
||||||
|
@end example
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@node sxml ssax input-parse
|
@node sxml ssax input-parse
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue