source: project/wiki/eggref/4/sxml-tools @ 13315

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

Remove newline in code bit

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