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

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

Make the example for sxml:id-alist less confusing

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