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

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

Document the new 'sxpath' module (not that there's much to document, but still)

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