source: project/wiki/eggref/4/sxpath @ 13357

Last change on this file since 13357 was 13357, checked in by sjamaan, 12 years ago

Rename sxml-tools wiki page to sxpath

File size: 31.8 KB
Line 
1[[tags:eggs]]
2
3This is version 0.1 of the '''sxpath''' extension library for Chicken Scheme.
4
5[[toc:]]
6
7== Description
8
9The sxpath parts of the [[http://cvs.sourceforge.net/viewcvs.py/ssax/sxml-tools/|sxml-tools]] from the [[http://ssax.sf.net|SSAX project]] at Sourceforge.
10
11== Documentation
12
13This egg provides the sxpath-related tools from the sxml-tools available
14in the SSAX/SXML Sourceforge project.
15
16These utilities are useful when you want to query SXML document trees,
17but full sxpath would be overkill.  Most of these procedures are
18faster than their sxpath equivalent, because they are very specific.
19But this also means they are very low-level, so you should use them
20only if you know what you're doing.
21
22Much documentation is available at
23[[http://www196.pair.com/lisovsky/xml/index.html|Lisovsky's XML page]]
24and the [[http://ssax.sf.net|SSAX homepage]].
25
26The initial documentation on this wiki page came straight from the
27comments in the extremely well-documented source code. It's
28recommended you read the code if you want to learn more.
29
30== sxpath-lolevel
31
32This section documents the low-level sxpath interface. It includes
33mostly-generic list and SXML operators.
34
35It consists of the extensions defined in {{sxml-tools.scm}} plus
36{{sxpathlib}} and {{sxpath-ext}}.  This is equivalent to the
37"low-level sxpath interface" described at
38[[http://www196.pair.com/lisovsky/query/sxpath/|the introduction to SXPath]].
39
40
41==== Predicates
42
43<procedure>(sxml:empty-element? obj)</procedure>
44
45Predicate which returns {{#t}} if given element {{obj}} is empty.
46Empty elements have no nested elements, text nodes, PIs, Comments or
47entities but may contain attributes or namespace-id.  It is a SXML
48counterpart of XML {{empty-element}}.
49
50<procedure>(sxml:shallow-normalized? obj)</procedure>
51
52Returns {{#t}} if the given {{obj}} is a shallow-normalized SXML
53element.  The element itself has to be normalised but its nested
54elements are not tested.
55
56<procedure>(sxml:normalized? obj)</procedure>
57
58Returns {{#t}} if the given {{obj}} is a normalized SXML element.  The element
59itself and all its nested elements have to be normalised.
60
61<procedure>(sxml:shallow-minimized? obj)</procedure>
62
63Returns {{#t}} if the given {{obj}} is a shallow-minimized SXML
64element.  The element itself has to be minimised but its nested
65elements are not tested.
66
67<procedure>(sxml:minimized? obj)</procedure>
68
69Returns {{#t}} if the given {{obj}} is a minimized SXML element.  The
70element itself and all its nested elements have to be minimised.
71
72==== Accessors
73
74These procedures obtain information about nodes, or their direct
75children.  They don't traverse subtrees.
76
77===== Normalization-independent accessors
78
79These accessors can be used on arbitrary, non-normalized SXML trees.
80Because of this, they are generally slower than the
81normalization-dependent variants listed in the next section.
82
83<procedure>(sxml:name node)</procedure>
84
85Returns a name of a given SXML node. It is introduced for the sake of
86encapsulation.
87
88<procedure>(sxml:element-name obj)</procedure>
89
90A checked version of sxml:name, which returns {{#f}} if the given
91{{obj}} is not a SXML element. Otherwise returns its name.
92
93<procedure>(sxml:node-name obj)</procedure>
94
95Safe version of sxml:name, which returns {{#f}} if the given {{obj}}
96is not a SXML node.  Otherwise returns its name.
97
98The difference between this and {{sxml::element-name}} is that a node
99can be one of {{@}}, {{@@}}, {{*PI*}}, {{*COMMENT*}} or {{*ENTITY*}}
100while an element must be a real element (any symbol not in that set is
101considered to be an element).
102
103<procedure>(sxml:ncname node)</procedure>
104
105Like {{sxml:name}}, except returns only the local part of the name
106(called an "NCName" in the
107[http://www.w3.org/TR/xml-names/|XML namespaces spec]).
108
109The node's name is interpreted as a "Qualified Name", a
110colon-separated name of which the last one is considered to be the
111local part.  If the name contains no colons, the name itself is
112returned.
113
114'''Important:''' Please note that while an SXML name is a symbol, this
115function returns a string.
116
117<procedure>(sxml:name->ns-id sxml-name)</procedure>
118
119Given a node name, return the namespace part of the name (called a
120{{namespace-id}}).  If the name contains no colons, returns {{#f}}.  See
121{{sxml:ncname}} for more info.
122
123'''Important:''' Please note that while an SXML name is a symbol, this
124function returns a string.
125
126<procedure>(sxml:content obj)</procedure>
127
128Retrieve the contents of an SXML element or nodeset.  Any non-element
129nodes (attributes, processing instructions, etc) are discarded,
130while the elements and text nodes are returned as a list of strings
131and nested elements in document order.  This list is empty if {{obj}}
132is an empty element or empty list.
133
134The inner elements are unmodified so they still contain attributes,
135but also comments or other non-element nodes.
136
137<examples>
138<example>
139<expr>
140(sxml:content
141  '(div (@ (class "content"))
142        (*COMMENT* "main contents start here")
143         "The document moved "
144         (a (@ (href "/other.xml")) "here")))
145</expr>
146<result>("The document moved " (a (@ (href "/other.xml")) "here"))</result>
147</example>
148</examples>
149
150<procedure>(sxml:text node)</procedure>
151
152Returns a string which combines all the character data from text node
153children of the given SXML element or "" if there are no text node
154children.  Note that it does not include text from descendant nodes,
155only direct children.
156
157<examples>
158<example>
159<expr>
160(sxml:text
161  '(div (@ (class "content"))
162        (*COMMENT* "main contents start here")
163         "The document moved "
164         (a (@ (href "/other.xml")) "here")))
165</expr>
166<result>("The document moved ")</result>
167</example>
168</examples>
169
170==== Normalization-dependent accessors
171
172"Universal" accessors are less effective but may be used for
173non-normalized SXML.  These safe accessors are named with suffix '-u'
174for "universal".
175
176"Fast" accessors are optimized for normalized SXML data.  They are not
177applicable to arbitrary non-normalized SXML data.  Their names have no
178specific suffixes.
179
180<procedure>(sxml:content-raw obj)</procedure>
181
182Returns all the content of normalized SXML element except attr-list
183and aux-list.  Thus it includes {{PI}}, {{COMMENT}} and {{ENTITY}}
184nodes as well as {{TEXT}} and {{ELEMENT}} nodes returned by
185{{sxml:content}}.  Returns a list of nodes in document order or empty
186list if {{obj}} is an empty element or an empty list.
187
188This function is faster than {{sxml:content}}.
189
190<procedure>(sxml:attr-list-u obj)</procedure>
191
192Returns the list of attributes for given element or nodeset.  Analog
193of {{((sxpath '(@ *)) obj)}}.  Empty list is returned if there is no
194list of attributes.
195
196<procedure>(sxml:aux-list obj)</procedure>
197<procedure>(sxml:aux-list-u obj)</procedure>
198
199Returns the list of auxiliary nodes for given element or nodeset.
200Analog of {{((sxpath '(@@ *)) obj)}}.  Empty list is returned if a
201list of auxiliary nodes is absent.
202
203<procedure>(sxml:aux-node obj aux-name)</procedure>
204
205Return the first aux-node with <aux-name> given in SXML element
206{{obj}} or {{#f}} is such a node is absent.
207
208'''NOTE:''' it returns just the ''first'' node found even if multiple
209nodes are present, so it's mostly intended for nodes with unique names.
210Use {{sxml:aux-nodes}} if you want all of them.
211
212<procedure>(sxml:aux-nodes obj aux-name)</procedure>
213   
214Return a list of aux-nodes with {{aux-name}} given in SXML element
215{{obj}} or {{'()}} if such a node is absent.
216
217<procedure>(sxml:attr obj attr-name)</procedure>
218
219Returns the value of the attribute with name {{attr-name}} in the
220given SXML element {{obj}}, or {{#f}} if no such attribute exists.
221
222<procedure>(sxml:attr-from-list attr-list name)</procedure>
223
224Returns the value of the attribute with name {{attr-name}} in the
225given list of attributes {{attr-list}}, or {{#f}} if no such attribute
226exists.  The list of attributes can be obtained from an element using
227the {{sxml:attr-list}} procedure.
228
229<procedure>(sxml:num-attr obj attr-name)</procedure>
230
231Returns the value of the numerical attribute with name {{attr-name}}
232in the given SXML element {{obj}}, or {{#f}} if no such attribute
233exists.  This value is converted from a string to a number.
234
235<procedure>(sxml:attr-u obj attr-name)</procedure>
236
237Accessor for an attribute {{attr-name}} of given SXML element {{obj}},
238which may also be an attributes-list or a nodeset (usually content of
239an SXML element)
240
241<procedure>(sxml:ns-list obj)</procedure>
242
243Returns the list of namespaces for given element.  Analog of
244{{((sxpath '(@@ *NAMESPACES* *)) obj)}}.  The empty list is returned
245if there are no namespaces.
246
247<procedure>(sxml:ns-id->nodes obj namespace-id)</procedure>
248
249Returns a list of namespace information lists that match the given
250{{namespace-id}} in SXML element {{obj}}.  Analog of
251{{((sxpath '(@@ *NAMESPACES* namespace-id)) obj)}}.
252The empty list is returned if there is no namespace with the given
253{{namespace-id}}.
254
255<examples>
256<example>
257<expr>
258(sxml:ns-id->nodes
259  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")))) 'c)
260</expr>
261<result>((c "http://www.cars.com/xml"))</result>
262</example>
263</examples>
264
265<procedure>(sxml:ns-id->uri obj namespace-id)</procedure>
266
267Returns the URI for the (first) namespace matching the given
268{{namespace-id}}, or {{#f}} if no namespace matches the given
269{{namespace-id}}.
270
271<examples>
272<example>
273<expr>
274(sxml:ns-id->uri
275  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")))) 'c)
276</expr>
277<result>"http://www.cars.com/xml"</result>
278</example>
279</examples>
280
281<procedure>(sxml:ns-uri->nodes obj uri)</procedure>
282
283Returns a list of namespace information lists that match the given
284{{uri}} in SXML element {{obj}}.
285
286<examples>
287<example>
288<expr>
289(sxml:ns-uri->nodes
290  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")
291                                 (d "http://www.cars.com/xml"))))
292  "http://www.cars.com/xml")
293</expr>
294<result>((c "http://www.cars.com/xml") (d "http://www.cars.com/xml"))</result>
295</example>
296</examples>
297
298<procedure>(sxml:ns-uri->id obj uri)</procedure>
299
300Returns the namespace id for the (first) namespace matching the given
301{{uri}}, or {{#f}} if no namespace matches the given {{uri}}.
302
303<examples>
304<example>
305<expr>
306(sxml:ns-uri->id
307  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")
308                                 (d "http://www.cars.com/xml"))))
309  "http://www.cars.com/xml")
310</expr>
311<result>c</result>
312</example>
313</examples>
314
315<procedure>(sxml:ns-id ns-list)</procedure>
316
317Given a namespace information list {{ns-list}}, returns the namespace ID.
318
319<procedure>(sxml:ns-uri ns-list)</procedure>
320
321Given a namespace information list {{ns-list}}, returns the namespace URI.
322
323<procedure>(sxml:ns-prefix ns-list)</procedure>
324
325Given a namespace information list {{ns-list}}, returns the namespace
326prefix if it is present in the list.  If it's not present, returns the
327namespace ID.
328
329==== Data modification procedures
330
331Constructors and mutators for normalized SXML data
332 
333'''Important:''' These functions are optimized for normalized SXML
334data.  They are ''not'' applicable to arbitrary non-normalized SXML
335data.
336
337Most of the functions are provided in two variants:
338
339# Side-effect intended functions for linear update of given elements.  Their names are ended with exclamation mark.
340# Pure functions without side-effects which return modified elements.
341
342
343<procedure>(sxml:change-content! obj new-content)</procedure>
344<procedure>(sxml:change-content obj new-content)</procedure>
345
346Change the content of given SXML element {{obj}} to {{new-content}}.
347If {{new-content}} is an empty list then the {{obj}} is transformed to
348an empty element.  The resulting SXML element is normalized.
349
350<procedure>(sxml:change-attrlist obj new-attrlist)</procedure>
351<procedure>(sxml:change-attrlist! obj new-attrlist)</procedure>
352
353Change the attribute list of the given SXML element {{obj}} to
354{{new-attrlist}}.
355
356<procedure>(sxml:change-name obj new-name)</procedure>
357<procedure>(sxml:change-name! obj new-name)</procedure>
358
359Change the name of the given SXML element {{obj}} to {{new-name}}.
360
361<procedure>(sxml:add-attr obj attr)</procedure>
362<procedure>(sxml:add-attr! obj attr)</procedure>
363
364Returns the given SXML element {{obj}} with the attribute {{attr}}
365added to the attribute list, or {{#f}} if the attribute already exists.
366
367<procedure>(sxml:change-attr obj attr)</procedure>
368<procedure>(sxml:change-attr! obj attr)</procedure>
369
370Returns SXML element {{obj}} with changed value of attribute {{attr}}
371or {{#f}} if where is no attribute with given name.
372
373{{attr}} is a list like it would occur as a member of an attribute
374list: {{(attr-name attr-value)}}.
375   
376<procedure>(sxml:set-attr obj attr)
377<procedure>(sxml:set-attr! obj attr)
378
379Returns SXML element {{obj}} with changed value of attribute {{attr}}.
380If there is no such attribute the new one is added.
381
382{{attr}} is a list like it would occur as a member of an attribute
383list: {{(attr-name attr-value)}}.
384
385<procedure>(sxml:add-aux obj aux-node)</procedure>
386<procedure>(sxml:add-aux! obj aux-node)</procedure>
387
388Returns SXML element {{obj}} with an auxiliary node {{aux-node}} added.
389
390<procedure>(sxml:squeeze obj)</procedure>
391<procedure>(sxml:squeeze! obj)</procedure>
392
393Returns a minimized and normalized SXML element {{obj}} with empty
394lists of attributes and aux-lists eliminated, in {{obj}} and all its
395descendants.
396   
397<procedure>(sxml:clean obj)</procedure>
398
399Returns a minimized and normalized SXML element {{obj}} with empty
400lists of attributes and '''all''' aux-lists eliminated, in {{obj}} and
401all its descendants.
402
403
404==== Sxpath-related procedures
405
406<procedure>(select-first-kid test-pred?)</procedure>
407
408Given a node, return the first child that satisfies the
409{{test-pred?}}.  Given a nodeset, traverse the set until a node is
410found whose first child matches the predicate.  Returns {{#f}} if
411there is no such a child to be found.
412
413<procedure>(sxml:node-parent rootnode)</procedure>
414
415Returns a function of one argument - an SXML element - which returns
416its parent node using {{*PARENT*}} pointer in the aux-list.
417{{'*TOP-PTR*}} may be used as a pointer to root node.  It returns an
418empty list when applied to the root node.
419
420<procedure>(sxml:add-parents obj [top-ptr])</procedure>
421
422Returns the SXML element {{obj}} annotated with {{*PARENT*}} pointers
423for {{obj}} and all its descendants.  If {{obj}} is not the root node
424(a node with a name of {{*TOP*}}), you must pass in the parent pointer
425for {{obj}} as {{top-ptr}}.
426
427'''Warning:''' This procedure mutates its {{obj}} argument.
428
429<procedure>(sxml:lookup id index)</procedure>
430
431Lookup an element using its ID.  {{index}} should be an alist of
432{{(id . element)}}.
433
434==== Markup generation
435
436===== XML
437
438<procedure>(sxml:attr->xml attr)</procedure>
439
440Returns a list containing tokens that when joined together form the
441attribute's XML output.
442
443'''Warning:''' This procedure assumes that the attribute's values have
444already been escaped (ie, {{sxml:string->xml has been called on the
445strings inside it}}).
446
447<examples>
448<example>
449<expr>(sxml:attr->xml '(href "http://example.com"))</expr>
450<result>(" " "href" "='" "http://example.com" "'")</result>
451</example>
452</examples>
453
454<procedure>(sxml:string->xml string)</procedure>
455
456Escape the {{string}} so it can be used anywhere in XML output.  This
457converts the {{<}}, {{>}}, {{'}}, {{"}} and {{&}} characters to their
458respective entities.
459
460<procedure>(sxml:sxml->xml tree)</procedure>
461
462Convert the {{tree}} of SXML nodes to a nested list of XML fragments.
463These fragments can be output by flattening the list and concatenating
464the strings inside it.
465
466==== HTML
467
468<procedure>(sxml:attr->html attr)</procedure>
469
470Returns a list containing tokens that when joined together form the
471attribute's HTML output.  The difference with the XML variant is that
472this encodes empty attribute values to attributes with no value (think
473{{selected}} in option elements, or {{checked}} in checkboxes).
474
475'''Warning:''' This procedure assumes that the attribute's values have
476already been escaped (ie, {{sxml:string->html has been called on the
477strings inside it}}).
478
479<procedure>(sxml:string->html string)</procedure>
480
481Escape the {{string}} so it can be used anywhere in XML output.  This
482converts the {{<}}, {{>}}, {{"}} and {{&}} characters to their
483respective entities.
484
485<procedure>(sxml:non-terminated-html-tag? tag)</procedure>
486
487Is the named {{tag}} one that is "self-closing" (ie, does not need to
488be terminated) in HTML 4.0?
489
490<procedure>(sxml:sxml->html tree)</procedure>
491
492Convert the {{tree}} of SXML nodes to a nested list of HTML fragments.
493These fragments can be output by flattening the list and concatenating
494the strings inside it.
495
496
497=== Procedures from sxpathlib
498
499==== Basic converters and applicators
500
501A converter is a function
502
503  type Converter = Node|Nodelist -> Nodelist
504
505A converter can also play a role of a predicate: in that case, if a
506converter, applied to a node or a nodelist, yields a non-empty
507nodelist, the converter-predicate is deemed satisfied. Throughout this
508file a nil nodelist is equivalent to {{#f}} in denoting a failure.
509
510<procedure>(nodeset? obj)</procedure>
511
512Returns {{#t}} if {{obj}} is a nodelist.
513
514<procedure>(as-nodeset obj)</procedure>
515
516If {{obj}} is a nodelist - returns it as is, otherwise wrap it in a
517list.
518
519==== Node test
520
521The following functions implement 'Node test's as defined in Sec. 2.3
522of the XPath document.  A node test is one of the components of a
523location step.  It is also a converter-predicate in SXPath.
524
525<procedure>(sxml:element? obj)</procedure>
526
527Predicate which returns {{#t}} if {{obj}} is SXML element, otherwise {{#f}}.
528
529<procedure>(ntype-names?? crit)</procedure>
530
531Takes a list of acceptable node names as a criterion and returns a
532function, which, when applied to a node, will return {{#t}} if the
533node name is present in criterion list and {{#f}} otherwise.
534
535   ntype-names?? :: ListOfNames -> Node -> Boolean
536
537<procedure>(ntype?? crit)</procedure>
538
539Takes a type criterion and returns a function, which, when applied to
540a node, will tell if the node satisfies the test.
541
542  ntype?? :: Crit -> Node -> Boolean
543
544The criterion {{crit}} is  one of the following symbols:
545
546; {{@}} : tests if the Node is an {{attributes-list}}
547; {{*}} : tests if the Node is an {{Element}}
548; {{*text*}} : tests if the Node is a text node
549; {{*data*}} : tests if the Node is a data node  (text, number, boolean, etc., but not pair)
550; {{*PI*}} : tests if the Node is a processing instructions node
551; {{*COMMENT*}} : tests if the Node is a comment node
552; {{*ENTITY*}} : tests if the Node is an entity node
553; {{*any*}} : {{#t}} for any type of Node
554; other symbol : tests if the Node has the right name given by the symbol
555
556<examples>
557<example>
558<expr>
559((ntype?? 'div) '(div (@ (class "greeting")) "hi"))
560</expr>
561<result>
562#t
563</result>
564</example>
565<example>
566<expr>
567((ntype?? 'div) '(span (@ (class "greeting")) "hi"))
568</expr>
569<result>
570#f
571</result>
572</example>
573<example>
574<expr>
575((ntype?? '*) '(span (@ (class "greeting")) "hi"))
576</expr>
577<result>
578#t
579</result>
580</example>
581</examples>
582   
583<procedure>(ntype-namespace-id?? ns-id)</procedure>
584
585This function takes a namespace-id, and returns a predicate
586{{Node -> Boolean}}, which is {{#t}} for nodes with the given
587namespace id. {{ns-id}} is a string.
588{{(ntype-namespace-id?? #f)}} will be {{#t}} for nodes with
589non-qualified names.
590
591<procedure>(sxml:complement pred)</procedure>
592
593This function takes a predicate and returns it complemented, that is
594if the given predicate yields {{#f}} or {{'()}} the complemented one
595yields the given node and vice versa.
596
597<procedure>(node-eq? other)</procedure>
598
599Returns a predicate procedure that, given a node, returns {{#t}} if
600the node is the exact same as {{other}}.
601
602<procedure>(node-equal? other)</procedure>
603
604Returns a predicate procedure that, given a node, returns {{#t}} if
605the node has the same contents as {{other}}.
606
607<procedure>(node-pos n)</procedure>
608
609Returns a procedure that, given a nodelist, returns a new nodelist
610containing only the {{n}}th element, counting from 1.  If {{n}} is
611negative, it returns a nodelist with the {{n}}th element counting from
612the right.  If no such node exists, returns the empty list.  {{n}} may
613not equal zero.
614
615<examples>
616<example>
617<expr>
618((node-pos 1) '((div "hi") (span "hello") (em "really, hi!")))
619</expr>
620<result>
621((div "hi"))
622</result>
623</example>
624<example>
625<expr>
626((node-pos 6) '((div "hi") (span "hello") (em "really, hi!")))
627</expr>
628<result>
629()
630</result>
631</example>
632<example>
633<expr>
634((node-pos -1) '((div "hi") (span "hello") (em "is this thing on?")))
635</expr>
636<result>
637((em "is this thing on?"))
638</result>
639</example>
640</examples>
641
642<procedure>(sxml:filter pred?)</procedure>
643
644Returns a procedure that accepts a nodelist or a node (which will be
645converted to a one-element nodelist) and returns only those nodes for
646which the predicate {{pred?}} does not return {{#f}} or {{'()}}.
647
648<examples>
649<example>
650<expr>
651((sxml:filter (ntype?? 'div)) '((div "hi") (span "hello") (div "still here?")))
652</expr>
653<result>
654((div "hi") (div "still here?"))
655</result>
656</example>
657</examples>
658
659<procedure>(take-until pred?)</procedure>
660<procedure>(take-after pred?)</procedure>
661
662Returns a procedure that accepts a node or a nodelist.
663
664The {{take-until}} variant returns everything ''before'' the first
665node for which the predicate {{pred?}} returns anything but {{#f}} or
666{{'()}}.  In other words, it returns the longest prefix for which the
667predicate returns {{#f}} or {{'()}}.
668
669The {{take-after}} variant returns everything ''after'' the first node
670for which the predicate {{pred?}} returns anything besides {{#f}} or
671{{'()}}.
672
673<examples>
674<example>
675<expr>
676((take-until (ntype?? 'span)) '((div "hi") (span "hello") (span "there") (div "still here?")))
677</expr>
678<result>
679((div "hi"))
680</result>
681</example>
682<example>
683<expr>
684((take-after (ntype?? 'span)) '((div "hi") (span "hello") (span "there") (div "still here?")))
685</expr>
686<result>
687((span "there") (div "still here?"))
688</result>
689</example>
690</examples>
691
692<procedure>(map-union proc list)</procedure>
693
694Apply {{proc}} to each element of the nodelist {{lst}} and return the
695list of results.  If {{proc}} returns a nodelist, splice it into the
696result (essentially returning a flattened nodelist).
697
698<procedure>(node-reverse node-or-nodelist)</procedure>
699
700Accepts a nodelist and reverses the nodes inside.  If a node is passed
701to this procedure, it returns a nodelist containing just that node.
702(it does not change the order of the children).
703
704==== Converter combinators
705
706Combinators are higher-order functions that transmogrify a converter
707or glue a sequence of converters into a single, non-trivial
708converter. The goal is to arrive at converters that correspond to
709XPath location paths.
710
711From a different point of view, a combinator is a fixed, named
712''pattern'' of applying converters. Given below is a complete set of
713such patterns that together implement XPath location path
714specification. As it turns out, all these combinators can be built
715from a small number of basic blocks; regular functional composition,
716{{map-union}} and filter applicators, and the nodelist union.
717
718<procedure>(select-kids pred?)</procedure>
719
720Returns a procedure that accepts a node and returns a nodelist of the
721node's children that satisfy {{pred?}} (ie, {{pred?}} returns anything
722but {{#f}} or {{'()}}).
723
724<procedure>(node-self pred?)</procedure>
725
726Similar to {{select-kids}} but applies to the node itself rather than
727to its children. The resulting Nodelist will contain either one
728component (the node), or will be empty (if the node failed the
729predicate).
730
731<procedure>(node-join . selectors)</procedure>
732
733Returns a procedure that accepts a nodelist or a node, and returns a
734nodelist with all the selectors applied to every node in sequence.
735The selectors must function as converter combinators, ie they must
736accept a ''node'' and output a ''nodelist''.
737
738<examples>
739<example>
740<expr>
741((node-join
742  (select-kids (ntype?? 'li))
743  sxml:content)
744 '((ul (@ (class "whiskies"))
745       (li "Ardbeg")
746       (li "Glenfarclas")
747       (li "Springbank"))))
748</expr>
749<result>
750("Ardbeg" "Glenfarclas" "Springbank")
751</result>
752</example>
753</examples>
754
755<procedure>(node-reduce . converters)</procedure>
756
757A regular functional composition of converters.
758
759From a different point of view,
760  ((apply node-reduce converters) nodelist)
761is equivalent to
762  (fold apply nodelist converters)
763i.e., folding, or reducing, a list of converters with the nodelist
764as a seed.
765
766
767<procedure>(node-or . converters)</procedure>
768
769This combinator applies all converters to a given node and produces
770the union of their results.  This combinator corresponds to a union,
771"{{|}}" operation for XPath location paths.
772
773<procedure>(node-closure test-pred?)</procedure>
774
775Select all ''descendants'' of a node that satisfy a
776converter-predicate.  This combinator is similar to {{select-kids}}
777but applies to grandchildren as well.
778
779<procedure>(node-trace title)</procedure>
780
781Returns a procedure that accepts a node or a nodelist, which it
782pretty-prints to the current output port, preceded by {{title}}.  It
783returns the node or the nodelist unchanged.  This is a useful
784debugging aid, since it doesn't really do anything besides print its
785argument and pass it on.
786
787<procedure>(sxml:node? obj)</procedure>
788
789Returns {{#t}} if the given {{obj}} is an SXML node, {{#f}} otherwise.
790A node is anything except an attribute list or an auxiliary list.
791
792<procedure>(sxml:attr-list node)</procedure>
793
794Returns the list of attributes for a given SXML node.  The empty list
795is returned if the given node is not an element, or if it has no list
796of attributes.
797
798This differs from {{sxml:attr-list-u}} in that this procedure accepts
799any SXML node while {{sxml:attr-list-u}} only accepts nodelists or
800elements.  This means that sxml:attr-list-u will throw an error if you
801pass it a text node (a string), while sxml:attr-list will not.
802
803<procedure>(sxml:attribute test-pred?)</procedure>
804
805Like {{sxml:filter}}, but considers the attributes instead of the
806nodes.  Returns a nodelist of attribtes that match {{test-pred?}}.
807
808<examples>
809<example>
810<expr>
811((sxml:attribute (ntype?? 'id))
812 '((div (@ (id "navigation")) "navigation here")
813   (div (@ (class "pullquote")) "random stuff")
814   (div (@ (id "main-content")) "lorem ipsum ...")))
815</expr>
816<result>
817((id "navigation") (id "main-content"))
818</result>
819</example>
820</examples>
821
822<procedure>(sxml:child test-pred?)</procedure>
823
824This procedure is similar to {{select-kids}}, but it returns an empty
825child-list for PI, Comment and Entity nodes.
826
827<procedure>(sxml:parent test-pred?)</procedure>
828
829Returns a procedure that accepts a root-node, and returns another
830procedure.  This second procedure accepts a nodeset (or a node) and
831returns the immediate parents of the nodes in the set, but only if
832for those parents that match the predicate.
833
834The root-node does not have to be the root node of the
835whole SXML tree -- it may be a root node of a branch of interest.
836
837This procedure can be used with any SXML node.
838
839==== Useful shortcuts
840
841<procedure>(node-parent node)</procedure>
842
843{{(node-parent rootnode)}} yields a converter that returns a parent of a
844node it is applied to. If applied to a nodelist, it returns the list
845of parents of nodes in the nodelist.
846
847This is equivalent to {{((sxml:parent (ntype? '*any*)) node)}}.
848
849<procedure>(sxml:child-nodes node)</procedure>
850
851Returns all the child nodes of the given {{node}}.
852
853This is equivalent to {{((sxml:child sxml:node?) node)}}.
854
855<procedure>(sxml:child-elements node)</procedure>
856
857Returns all the child ''elements'' of the given {{node}}. (ie,
858excludes any textnodes).
859
860This is equivalent to {{((select-kids sxml:element?) node)}}.
861
862=== Procedures from sxpath-ext
863
864==== SXML counterparts to W3C XPath Core Functions Library
865
866<procedure>(sxml:string object)</procedure>
867
868The counterpart to XPath 'string' function (section 4.2 XPath 1.0 Rec.).
869Converts a given object to a string.
870
871Notes:
872# When converting a nodeset, document order is not preserved
873# {{number->string}} returns the result in a form which is slightly different from XPath Rec. specification
874
875<procedure>(sxml:boolean object)</procedure>
876
877The counterpart to XPath 'boolean' function (section 4.3 XPath Rec.).
878Converts its argument to a boolean.
879
880<procedure>(sxml:number object)</procedure>
881
882The counterpart to XPath 'number' function (section 4.4 XPath Rec.).
883Converts its argument to a number.
884
885Notes:
886# The argument is not optional (yet?)
887# string->number conversion is not IEEE 754 round-to-nearest
888# NaN is represented as 0
889
890<procedure>(sxml:string-value node)</procedure>
891
892Returns a string value for a given node in accordance to
893XPath Rec. 5.1 - 5.7
894
895<procedure>(sxml:id id-index)</procedure>
896
897Returns a procedure that accepts a nodeset and returns a nodeset
898containing the elements in the id-index that match the string-values
899of each entry of the nodeset.  XPath Rec. 4.1
900
901The {{id-index}} is an alist with unique IDs as key, and elements as
902values:
903
904  id-index = ( (id-value . element) (id-value . element) ... )
905
906==== Comparators for XPath objects
907
908<procedure>(sxml:list-head list n)</procedure>
909
910Returns the {{n}} first members of {{list}}.  Mostly equivalent to
911SRFI-1's {{take}} procedure, except it returns the {{list}} if {{n}}
912is larger than the length of said list, instead of throwing an error.
913
914<procedure>(sxml:merge-sort less-than? list)</procedure>
915
916Returns the sorted list, the smallest member first.
917  less-than? ::= (lambda (obj1 obj2) ...)
918{{less-than?}} returns {{#t}} if {{obj1 < obj2}} with respect to the
919given ordering.
920
921<procedure>(sxml:equality-cmp bool=? number=? string=?)</procedure>
922
923A helper for XPath equality operations: {{=}} , {{!=}}.  The
924{{bool=?}}, {{number=?}} and {{string=?}} arguments are comparison
925operations for booleans, numbers and strings respectively.
926
927Returns a procedure that accepts two objects, looks at the first
928object's type and applies the correct comparison predicate to it.
929Type coercion takes place depending on the rules described in the
930XPath 1.0 spec, section 3.4 ("Booleans").
931
932<procedure>(sxml:equal? obj1 obj2)</procedure>
933<procedure>(sxml:not-equal? obj1 obj2)</procedure>
934
935Equality procedures with the default comparison operators {{eq?}},
936{{=}} and {{string=?}}, or their inverse, respectively.
937
938<procedure>(sxml:relational-cmp op)</procedure>
939
940A helper for XPath relational operations: {{<}}, {{>}}, {{<=}}, {{>=}}
941for two XPath objects.  {{op}} is one of these operators.
942
943Returns a procedure that accepts two objects and returns the value of
944the procedure applied to these objects, converted according to the
945coercion rules described in the XPath 1.0 spec, section 3.4
946("Booleans").
947
948==== XPath axes
949
950<procedure>(sxml:ancestor test-pred?)</procedure>
951
952Like {{sxml:parent}}, except it returns all the ancestors that match
953{{test-pred?}}, not just the immediate parent.
954
955<procedure>(sxml:ancestor-or-self test-pred?)</procedure>
956
957Like {{sxml:ancestor}}, except also allows the node itself to match
958the predicate.
959
960<procedure>(sxml:descendant test-pred?)</procedure>
961
962Like {{node-closure}}, except the resulting nodeset is in depth-first
963order instead of breadth-first.
964
965<procedure>(sxml:descendant-or-self test-pred?)</procedure>
966
967Like {{sxml:descendant}}, except also allows the node itself to match
968the predicate.
969
970<procedure>(sxml:following test-pred?)</procedure>
971
972Returns a procedure that accepts a root node and returns a new
973procedure that accepts a node and returns all nodes following this
974node in the document source matching the predicate.
975
976<procedure>(sxml:following-sibling test-pred?)</procedure>
977
978Like {{sxml:following}}, except only siblings (nodes at the same level
979under the same parent) are returned.
980
981<procedure>(sxml:preceding test-pred?)</procedure>
982
983Returns a procedure that accepts a root node and returns a new
984procedure that accepts a node and returns all nodes preceding this
985node in the document source matching the predicate.
986
987<procedure>(sxml:preceding-sibling test-pred?)</procedure>
988
989Like {{sxml:preceding}}, except only siblings (nodes at the same level
990under the same parent) are returned.
991
992<procedure>(sxml:namespace test-pred?)</procedure>
993
994Returns a procedure that accepts a nodeset and returns the namespace
995lists of the nodes matching {{test-pred?}}.
996
997
998== About this egg
999
1000=== Author
1001
1002[[http://okmij.org/ftp/|Oleg Kiselyov]], [[http://www196.pair.com/lisovsky/|Kirill Lisovsky]], [[http://modis.ispras.ru/Lizorkin/index.html|Dmitry Lizorkin]].
1003
1004=== Version history
1005
1006; 0.1 : Split up the old sxml-tools egg into sxpath
1007
1008=== License
1009
1010The sxml-tools are in the public domain.
Note: See TracBrowser for help on using the repository browser.