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

Last change on this file since 13313 was 13313, checked in by sjamaan, 11 years ago

Fix formatting of link

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)</procedures>
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 {{((sxpath '(@@
246*NAMESPACES* namespace-id)) obj)}}. The empty list is returned if
247there is no namespace with the given {{namespace-id}}.
248
249<examples>
250<example>
251<expr>
252(sxml:ns-id->nodes
253  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")))) 'c)
254</expr>
255<result>((c "http://www.cars.com/xml"))</result>
256</example>
257</examples>
258
259<procedure>(sxml:ns-id->uri obj namespace-id)</procedure>
260
261Returns the URI for the (first) namespace matching the given
262{{namespace-id}}, or {{#f}} if no namespace matches the given
263{{namespace-id}}.
264
265<examples>
266<example>
267<expr>
268(sxml:ns-id->uri
269  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")))) 'c)
270</expr>
271<result>"http://www.cars.com/xml"</result>
272</example>
273</examples>
274
275<procedure>(sxml:ns-uri->nodes obj uri)</procedure>
276
277Returns a list of namespace information lists that match the given
278{{uri}} in SXML element {{obj}}.
279
280<examples>
281<example>
282<expr>
283(sxml:ns-uri->nodes
284  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")
285                                 (d "http://www.cars.com/xml"))))
286  "http://www.cars.com/xml")
287</expr>
288<result>((c "http://www.cars.com/xml") (d "http://www.cars.com/xml"))</example>
289</example>
290</examples>
291
292<procedure>(sxml:ns-uri->id obj uri)</procedure>
293
294Returns the namespace id for the (first) namespace matching the given
295{{uri}}, or {{#f}} if no namespace matches the given {{uri}}.
296
297<examples>
298<example>
299<expr>
300(sxml:ns-uri->id
301  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")
302                                 (d "http://www.cars.com/xml"))))
303  "http://www.cars.com/xml")
304</expr>
305<result>c</example>
306</example>
307</examples>
308
309<procedure>(sxml:ns-id ns-list)</procedure>
310
311Given a namespace information list {{ns-list}}, returns the namespace ID.
312
313<procedure>(sxml:ns-uri ns-list)</procedure>
314
315Given a namespace information list {{ns-list}}, returns the namespace URI.
316
317<procedure>(sxml:ns-prefix ns-list)</procedure>
318
319Given a namespace information list {{ns-list}}, returns the namespace
320prefix if it is present in the list.  If it's not present, returns the
321namespace ID.
322
323==== Data modification procedures
324
325Constructors and mutators for normalized SXML data
326 
327'''Important:''' These functions are optimized for normalized SXML
328data.  They are ''not'' applicable to arbitrary non-normalized SXML
329data.
330
331Most of the functions are provided in two variants:
332
333# Side-effect intended functions for linear update of given elements.  Their names are ended with exclamation mark.
334# Pure functions without side-effects which return modified elements.
335
336
337<procedure>(sxml:change-content! obj new-content)</procedure>
338<procedure>(sxml:change-content obj new-content)</procedure>
339
340Change the content of given SXML element {{obj}} to {{new-content}}.
341If {{new-content}} is an empty list then the {{obj}} is transformed to
342an empty element.  The resulting SXML element is normalized.
343
344<procedure>(sxml:change-attrlist obj new-attrlist)</procedure>
345<procedure>(sxml:change-attrlist! obj new-attrlist)</procedure>
346
347Change the attribute list of the given SXML element {{obj}} to
348{{new-attrlist}}.
349
350<procedure>(sxml:change-name obj new-name)</procedure>
351<procedure>(sxml:change-name! obj new-name)</procedure>
352
353Change the name of the given SXML element {{obj}} to {{new-name}}.
354
355<procedure>(sxml:add-attr obj attr)</procedure>
356<procedure>(sxml:add-attr! obj attr)</procedure>
357
358Returns the given SXML element {{obj}} with the attribute {{attr}}
359added to the attribute list, or {{#f}} if the attribute already exists.
360
361<procedure>(sxml:change-attr obj attr)</procedure>
362<procedure>(sxml:change-attr! obj attr)</procedure>
363
364Returns SXML element {{obj}} with changed value of attribute {{attr}}
365or {{#f}} if where is no attribute with given name.
366
367{{attr}} is a list like it would occur as a member of an attribute
368list: {{(attr-name attr-value)}}.
369   
370<procedure>(sxml:set-attr obj attr)
371<procedure>(sxml:set-attr! obj attr)
372
373Returns SXML element {{obj}} with changed value of attribute {{attr}}.
374If there is no such attribute the new one is added.
375
376{{attr}} is a list like it would occur as a member of an attribute
377list: {{(attr-name attr-value)}}.
378
379<procedure>(sxml:add-aux obj aux-node)</procedure>
380<procedure>(sxml:add-aux! obj aux-node)</procedure>
381
382Returns SXML element {{obj}} with an auxiliary node {{aux-node}} added.
383
384<procedure>(sxml:squeeze obj)</procedure>
385<procedure>(sxml:squeeze! obj)</procedure>
386
387Returns a minimized and normalized SXML element {{obj}} with empty
388lists of attributes and aux-lists eliminated, in {{obj}} and all its
389descendants.
390   
391<procedure>(sxml:clean obj)</procedure>
392
393Returns a minimized and normalized SXML element {{obj}} with empty
394lists of attributes and '''all''' aux-lists eliminated, in {{obj}} and
395all its descendants.
396
397
398==== Sxpath-related procedures
399
400<procedure>(select-first-kid test-pred?)</procedure>
401
402Given a node, return the first child that satisfies the
403{{test-pred?}}.  Given a nodeset, traverse the set until a node is
404found whose first child matches the predicate.  Returns {{#f}} if
405there is no such a child to be found.
406
407<procedure>(sxml:node-parent rootnode)</procedure>
408
409Returns a function of one argument - an SXML element - which returns
410its parent node using {{*PARENT*}} pointer in the aux-list.
411{{'*TOP-PTR*}} may be used as a pointer to root node.  It returns an
412empty list when applied to the root node.
413
414<procedure>(sxml:add-parents obj [top-ptr])</procedure>
415
416Returns the SXML element {{obj}} annotated with {{*PARENT*}} pointers
417for {{obj}} and all its descendants.  If {{obj}} is not the root node
418(a node with a name of {{*TOP*}}), you must pass in the parent pointer
419for {{obj}} as {{top-ptr}}.
420
421'''Warning:''' This procedure mutates its {{obj}} argument.
422
423<procedure>(sxml:lookup id index)</procedure>
424
425Lookup an element using its ID.  {{index}} should be an alist of
426{{(id . element)}}.
427
428==== Markup generation
429
430===== XML
431
432<procedure>(sxml:attr->xml attr)</procedure>
433
434Returns a list containing tokens that when joined together form the
435attribute's XML output.
436
437'''Warning:''' This procedure assumes that the attribute's values have
438already been escaped (ie, {{sxml:string->xml has been called on the
439strings inside it}}).
440
441<examples>
442<example>
443<expr>(sxml:attr->xml '(href "http://example.com"))</expr>
444<result>(" " "href" "='" "http://example.com" "'")</result>
445</example>
446</examples>
447
448<procedure>(sxml:string->xml string)</procedure>
449
450Escape the {{string}} so it can be used anywhere in XML output.  This
451converts the {{<}}, {{>}}, {{'}}, {{"}} and {{&}} characters to their
452respective entities.
453
454<procedure>(sxml:sxml->xml tree)</procedure>
455
456Convert the {{tree}} of SXML nodes to a nested list of XML fragments.
457These fragments can be output by flattening the list and concatenating
458the strings inside it.
459
460==== HTML
461
462<procedure>(sxml:attr->html attr)</procedure>
463
464Returns a list containing tokens that when joined together form the
465attribute's HTML output.  The difference with the XML variant is that
466this encodes empty attribute values to attributes with no value (think
467{{selected}} in option elements, or {{checked}} in checkboxes).
468
469'''Warning:''' This procedure assumes that the attribute's values have
470already been escaped (ie, {{sxml:string->html has been called on the
471strings inside it}}).
472
473<procedure>(sxml:string->html string)</procedure>
474
475Escape the {{string}} so it can be used anywhere in XML output.  This
476converts the {{<}}, {{>}}, {{"}} and {{&}} characters to their
477respective entities.
478
479<procedure>(sxml:non-terminated-html-tag? tag)</procedure>
480
481Is the named {{tag}} one that is "self-closing" (ie, does not need to
482be terminated) in HTML 4.0?
483
484<procedure>(sxml:sxml->html tree)</procedure>
485
486Convert the {{tree}} of SXML nodes to a nested list of HTML fragments.
487These fragments can be output by flattening the list and concatenating
488the strings inside it.
489
490
491=== Procedures from sxpathlib
492
493==== Basic converters and applicators
494
495A converter is a function
496
497  type Converter = Node|Nodelist -> Nodelist
498
499A converter can also play a role of a predicate: in that case, if a
500converter, applied to a node or a nodelist, yields a non-empty
501nodelist, the converter-predicate is deemed satisfied. Throughout this
502file a nil nodelist is equivalent to {{#f}} in denoting a failure.
503
504<procedure>(nodeset? obj)</procedure>
505
506Returns {{#t}} if {{obj}} is a nodelist.
507
508<procedure>(as-nodeset obj)</procedure>
509
510If {{obj}} is a nodelist - returns it as is, otherwise wrap it in a
511list.
512
513==== Node test
514
515The following functions implement 'Node test's as defined in Sec. 2.3
516of the XPath document.  A node test is one of the components of a
517location step.  It is also a converter-predicate in SXPath.
518
519<procedure>(sxml:element? obj)</procedure>
520
521Predicate which returns {{#t}} if {{obj}} is SXML element, otherwise {{#f}}.
522
523<procedure>(ntype-names?? crit)</procedure>
524
525Takes a list of acceptable node names as a criterion and returns a
526function, which, when applied to a node, will return {{#t}} if the
527node name is present in criterion list and {{#f}} otherwise.
528
529   ntype-names?? :: ListOfNames -> Node -> Boolean
530
531<procedure>(ntype?? crit)</procedure>
532
533Takes a type criterion and returns a function, which, when applied to
534a node, will tell if the node satisfies the test.
535
536  ntype?? :: Crit -> Node -> Boolean
537
538The criterion {{crit}} is  one of the following symbols:
539
540; {{@}} : tests if the Node is an {{attributes-list}}
541; {{*}} : tests if the Node is an {{Element}}
542; {{*text*}} : tests if the Node is a text node
543; {{*data*}} : tests if the Node is a data node  (text, number, boolean, etc., but not pair)
544; {{*PI*}} : tests if the Node is a processing instructions node
545; {{*COMMENT*}} : tests if the Node is a comment node
546; {{*ENTITY*}} : tests if the Node is an entity node
547; {{*any*}} : {{#t}} for any type of Node
548; other symbol : tests if the Node has the right name given by the symbol
549
550<examples>
551<example>
552<expr>
553((ntype?? 'div) '(div (@ (class "greeting")) "hi"))
554</expr>
555<result>
556#t
557</result>
558</example>
559<example>
560<expr>
561((ntype?? 'div) '(span (@ (class "greeting")) "hi"))
562</expr>
563<result>
564#f
565</result>
566</example>
567<example>
568<expr>
569((ntype?? '*) '(span (@ (class "greeting")) "hi"))
570</expr>
571<result>
572#t
573</result>
574</example>
575</examples>
576   
577<procedure>(ntype-namespace-id?? ns-id)</procedure>
578
579This function takes a namespace-id, and returns a predicate
580{{Node -> Boolean}}, which is {{#t}} for nodes with the given
581namespace id. {{ns-id}} is a string.
582{{(ntype-namespace-id?? #f)}} will be {{#t}} for nodes with
583non-qualified names.
584
585<procedure>(sxml:complement pred)</procedure>
586
587This function takes a predicate and returns it complemented, that is
588if the given predicate yields {{#f}} or {{'()}} the complemented one
589yields the given node and vice versa.
590
591<procedure>(node-eq? other)</procedure>
592
593Returns a predicate procedure that, given a node, returns {{#t}} if
594the node is the exact same as {{other}}.
595
596<procedure>(node-equal? other)</procedure>
597
598Returns a predicate procedure that, given a node, returns {{#t}} if
599the node has the same contents as {{other}}.
600
601<procedure>(node-pos n)</procedure>
602
603Returns a procedure that, given a nodelist, returns a new nodelist
604containing only the {{n}}th element, counting from 1.  If {{n}} is
605negative, it returns a nodelist with the {{n}}th element counting from
606the right.  If no such node exists, returns the empty list.  {{n}} may
607not equal zero.
608
609<examples>
610<example>
611<expr>
612((node-pos 1) '((div "hi") (span "hello") (em "really, hi!")))
613</expr>
614<result>
615((div "hi"))
616</result>
617</example>
618<example>
619<expr>
620((node-pos 6) '((div "hi") (span "hello") (em "really, hi!")))
621</expr>
622<result>
623()
624</result>
625</example>
626<example>
627<expr>
628((node-pos -1) '((div "hi") (span "hello") (em "is this thing on?")))
629</expr>
630<result>
631((em "is this thing on?"))
632</result>
633</example>
634</examples>
635
636<procedure>(sxml:filter pred?)</procedure>
637
638Returns a procedure that accepts a nodelist or a node (which will be
639converted to a one-element nodelist) and returns only those nodes for
640which the predicate {{pred?}} does not return {{#f}} or {{'()}}.
641
642<examples>
643<example>
644<expr>
645((sxml:filter (ntype?? 'div)) '((div "hi") (span "hello") (div "still here?")))
646</expr>
647<result>
648((div "hi") (div "still here?"))
649</result>
650</example>
651</examples>
652
653<procedure>(take-until pred?)</procedure>
654<procedure>(take-after pred?)</procedure>
655
656Returns a procedure that accepts a node or a nodelist.
657
658The {{take-until}} variant returns everything ''before'' the first
659node for which the predicate {{pred?}} returns anything but {{#f}} or
660{{'()}}.  In other words, it returns the longest prefix for which the
661predicate returns {{#f}} or {{'()}}.
662
663The {{take-after}} variant returns everything ''after'' the first node
664for which the predicate {{pred?}} returns anything besides {{#f}} or
665{{'()}}.
666
667<examples>
668<example>
669<expr>
670((take-until (ntype?? 'span)) '((div "hi") (span "hello") (span "there") (div "still here?")))
671</expr>
672<result>
673((div "hi"))
674</result>
675</example>
676<example>
677<expr>
678((take-after (ntype?? 'span)) '((div "hi") (span "hello") (span "there") (div "still here?")))
679</expr>
680<result>
681((span "there") (div "still here?"))
682</result>
683</example>
684</examples>
685
686<procedure>(map-union proc list)</procedure>
687
688Apply {{proc}} to each element of the nodelist {{lst}} and return the
689list of results.  If {{proc}} returns a nodelist, splice it into the
690result (essentially returning a flattened nodelist).
691
692<procedure>(node-reverse node-or-nodelist)</procedure>
693
694Accepts a nodelist and reverses the nodes inside.  If a node is passed
695to this procedure, it returns a nodelist containing just that node.
696(it does not change the order of the children).
697
698==== Converter combinators
699
700Combinators are higher-order functions that transmogrify a converter
701or glue a sequence of converters into a single, non-trivial
702converter. The goal is to arrive at converters that correspond to
703XPath location paths.
704
705From a different point of view, a combinator is a fixed, named
706''pattern'' of applying converters. Given below is a complete set of
707such patterns that together implement XPath location path
708specification. As it turns out, all these combinators can be built
709from a small number of basic blocks; regular functional composition,
710{{map-union}} and filter applicators, and the nodelist union.
711
712<procedure>(select-kids pred?)</procedure>
713
714Returns a procedure that accepts a node and returns a nodelist of the
715node's children that satisfy {{pred?}} (ie, {{pred?}} returns anything
716but {{#f}} or {{'()}}).
717
718<procedure>(node-self pred?)</procedure>
719
720Similar to {{select-kids}} but applies to the node itself rather than
721to its children. The resulting Nodelist will contain either one
722component (the node), or will be empty (if the node failed the
723predicate).
724
725<procedure>(node-join . selectors)</procedure>
726
727Returns a procedure that accepts a nodelist or a node, and returns a
728nodelist with all the selectors applied to every node in sequence.
729The selectors must function as converter combinators, ie they must
730accept a ''node'' and output a ''nodelist''.
731
732<examples>
733<example>
734<expr>
735((node-join
736  (select-kids (ntype?? 'li))
737  sxml:content)
738 '((ul (@ (class "whiskies"))
739       (li "Ardbeg")
740       (li "Glenfarclas")
741       (li "Springbank"))))
742</expr>
743<result>
744("Ardbeg" "Glenfarclas" "Springbank")
745</result>
746</example>
747</examples>
748
749<procedure>(node-reduce . converters)</procedure>
750
751A regular functional composition of converters.
752
753From a different point of view,
754  ((apply node-reduce converters) nodelist)
755is equivalent to
756  (fold apply nodelist converters)
757i.e., folding, or reducing, a list of converters with the nodelist
758as a seed.
759
760
761<procedure>(node-or . converters)</procedure>
762
763This combinator applies all converters to a given node and produces
764the union of their results.  This combinator corresponds to a union,
765"{{|}}" operation for XPath location paths.
766
767<procedure>(node-closure test-pred?)</procedure>
768
769Select all ''descendants'' of a node that satisfy a
770converter-predicate.  This combinator is similar to {{select-kids}}
771but applies to grandchildren as well.
772
773<procedure>(node-trace title)</procedure>
774
775Returns a procedure that accepts a node or a nodelist, which it
776pretty-prints to the current output port, preceded by {{title}}.  It
777returns the node or the nodelist unchanged.  This is a useful
778debugging aid, since it doesn't really do anything besides print its
779argument and pass it on.
780
781<procedure>(sxml:node? obj)</procedure>
782
783Returns {{#t}} if the given {{obj}} is an SXML node, {{#f}} otherwise.
784A node is anything except an attribute list or an auxiliary list.
785
786<procedure>(sxml:attr-list node)</procedure>
787
788Returns the list of attributes for a given SXML node.  The empty list
789is returned if the given node is not an element, or if it has no list
790of attributes.
791
792This differs from {{sxml:attr-list-u}} in that this procedure accepts
793any SXML node while {{sxml:attr-list-u}} only accepts nodelists or
794elements.  This means that sxml:attr-list-u will throw an error if you
795pass it a text node (a string), while sxml:attr-list will not.
796
797<procedure>(sxml:attribute test-pred?)</procedure>
798
799Like {{sxml:filter}}, but considers the attributes instead of the
800nodes.  Returns a nodelist of attribtes that match {{test-pred?}}.
801
802<examples>
803<example>
804<expr>
805((sxml:attribute (ntype?? 'id))
806 '((div (@ (id "navigation")) "navigation here")
807   (div (@ (class "pullquote")) "random stuff")
808   (div (@ (id "main-content")) "lorem ipsum ...")))
809</expr>
810<result>
811((id "navigation") (id "main-content"))
812</result>
813</example>
814</examples>
815
816<procedure>(sxml:child test-pred?)</procedure>
817
818This procedure is similar to {{select-kids}}, but it returns an empty
819child-list for PI, Comment and Entity nodes.
820
821<procedure>(sxml:parent test-pred?)</procedure>
822
823Given a predicate, it returns a function
824  RootNode -> Converter
825which in turn yields a
826  node -> parent
827converter when applied to a rootnode.
828
829Thus, such a converter may be constructed using
830  ((sxml:parent test-pred) rootnode)
831and returns a parent of a node it is applied to.
832
833If applied to a nodelist, it returns the list of parents of nodes in
834the nodelist. The rootnode 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== About this egg
863
864=== Author
865
866[[http://okmij.org/ftp/|Oleg Kiselyov]], [[http://www196.pair.com/lisovsky/|Kirill Lisovsky]], [[http://modis.ispras.ru/Lizorkin/index.html|Dmitry Lizorkin]].
867
868=== Version history
869
870; 1.3 : Port to Chicken 4, separation of sxml-tools/sxpathlib from sxpath
871; 1.2 : uses {{string-intersperse}} and {{concatenate}} instead of {{apply string-append}} and {{apply append}} to circumvent argument count limit [felix]
872; 1.1 : exports/imports support, split stx-engine into syntax & support files [Kon Lovett]
873; 1.0 : Initial release [zbigniew]
874
875=== License
876
877The sxml-tools are in the public domain.
Note: See TracBrowser for help on using the repository browser.