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

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

Remove mention of filenames, as it is not very relevant

File size: 44.3 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.  This is equivalent to the
413"low-level sxpath interface" described at
414[[http://www196.pair.com/lisovsky/query/sxpath/|the introduction to SXPath]].
415
416These utilities are useful when you want to query SXML document trees,
417but full sxpath would be overkill.  Most of these procedures are
418faster than their sxpath equivalent, because they are very specific.
419But this also means they are very low-level, so you should use them
420only if you know what you're doing.
421
422
423==== Predicates
424
425<procedure>(sxml:empty-element? obj)</procedure>
426
427Predicate which returns {{#t}} if given element {{obj}} is empty.
428Empty elements have no nested elements, text nodes, PIs, Comments or
429entities but may contain attributes or namespace-id.  It is a SXML
430counterpart of XML {{empty-element}}.
431
432<procedure>(sxml:shallow-normalized? obj)</procedure>
433
434Returns {{#t}} if the given {{obj}} is a shallow-normalized SXML
435element.  The element itself has to be normalised but its nested
436elements are not tested.
437
438<procedure>(sxml:normalized? obj)</procedure>
439
440Returns {{#t}} if the given {{obj}} is a normalized SXML element.  The element
441itself and all its nested elements have to be normalised.
442
443<procedure>(sxml:shallow-minimized? obj)</procedure>
444
445Returns {{#t}} if the given {{obj}} is a shallow-minimized SXML
446element.  The element itself has to be minimised but its nested
447elements are not tested.
448
449<procedure>(sxml:minimized? obj)</procedure>
450
451Returns {{#t}} if the given {{obj}} is a minimized SXML element.  The
452element itself and all its nested elements have to be minimised.
453
454==== Accessors
455
456These procedures obtain information about nodes, or their direct
457children.  They don't traverse subtrees.
458
459===== Normalization-independent accessors
460
461These accessors can be used on arbitrary, non-normalized SXML trees.
462Because of this, they are generally slower than the
463normalization-dependent variants listed in the next section.
464
465<procedure>(sxml:name node)</procedure>
466
467Returns a name of a given SXML node. It is introduced for the sake of
468encapsulation.
469
470<procedure>(sxml:element-name obj)</procedure>
471
472A checked version of sxml:name, which returns {{#f}} if the given
473{{obj}} is not a SXML element. Otherwise returns its name.
474
475<procedure>(sxml:node-name obj)</procedure>
476
477Safe version of sxml:name, which returns {{#f}} if the given {{obj}}
478is not a SXML node.  Otherwise returns its name.
479
480The difference between this and {{sxml::element-name}} is that a node
481can be one of {{@}}, {{@@}}, {{*PI*}}, {{*COMMENT*}} or {{*ENTITY*}}
482while an element must be a real element (any symbol not in that set is
483considered to be an element).
484
485<procedure>(sxml:ncname node)</procedure>
486
487Like {{sxml:name}}, except returns only the local part of the name
488(called an "NCName" in the
489[[http://www.w3.org/TR/xml-names/|XML namespaces spec]]).
490
491The node's name is interpreted as a "Qualified Name", a
492colon-separated name of which the last one is considered to be the
493local part.  If the name contains no colons, the name itself is
494returned.
495
496'''Important:''' Please note that while an SXML name is a symbol, this
497function returns a string.
498
499<procedure>(sxml:name->ns-id sxml-name)</procedure>
500
501Given a node name, return the namespace part of the name (called a
502{{namespace-id}}).  If the name contains no colons, returns {{#f}}.  See
503{{sxml:ncname}} for more info.
504
505'''Important:''' Please note that while an SXML name is a symbol, this
506function returns a string.
507
508<procedure>(sxml:content obj)</procedure>
509
510Retrieve the contents of an SXML element or nodeset.  Any non-element
511nodes (attributes, processing instructions, etc) are discarded,
512while the elements and text nodes are returned as a list of strings
513and nested elements in document order.  This list is empty if {{obj}}
514is an empty element or empty list.
515
516The inner elements are unmodified so they still contain attributes,
517but also comments or other non-element nodes.
518
519<examples>
520<example>
521<expr>
522(sxml:content
523  '(div (@ (class "content"))
524        (*COMMENT* "main contents start here")
525         "The document moved "
526         (a (@ (href "/other.xml")) "here")))
527</expr>
528<result>("The document moved " (a (@ (href "/other.xml")) "here"))</result>
529</example>
530</examples>
531
532<procedure>(sxml:text node)</procedure>
533
534Returns a string which combines all the character data from text node
535children of the given SXML element or "" if there are no text node
536children.  Note that it does not include text from descendant nodes,
537only direct children.
538
539<examples>
540<example>
541<expr>
542(sxml:text
543  '(div (@ (class "content"))
544        (*COMMENT* "main contents start here")
545         "The document moved "
546         (a (@ (href "/other.xml")) "here")))
547</expr>
548<result>("The document moved ")</result>
549</example>
550</examples>
551
552==== Normalization-dependent accessors
553
554"Universal" accessors are less effective but may be used for
555non-normalized SXML.  These safe accessors are named with suffix '-u'
556for "universal".
557
558"Fast" accessors are optimized for normalized SXML data.  They are not
559applicable to arbitrary non-normalized SXML data.  Their names have no
560specific suffixes.
561
562<procedure>(sxml:content-raw obj)</procedure>
563
564Returns all the content of normalized SXML element except attr-list
565and aux-list.  Thus it includes {{PI}}, {{COMMENT}} and {{ENTITY}}
566nodes as well as {{TEXT}} and {{ELEMENT}} nodes returned by
567{{sxml:content}}.  Returns a list of nodes in document order or empty
568list if {{obj}} is an empty element or an empty list.
569
570This function is faster than {{sxml:content}}.
571
572<procedure>(sxml:attr-list-u obj)</procedure>
573
574Returns the list of attributes for given element or nodeset.  Analog
575of {{((sxpath '(@ *)) obj)}}.  Empty list is returned if there is no
576list of attributes.
577
578<procedure>(sxml:aux-list obj)</procedure>
579<procedure>(sxml:aux-list-u obj)</procedure>
580
581Returns the list of auxiliary nodes for given element or nodeset.
582Analog of {{((sxpath '(@@ *)) obj)}}.  Empty list is returned if a
583list of auxiliary nodes is absent.
584
585<procedure>(sxml:aux-node obj aux-name)</procedure>
586
587Return the first aux-node with <aux-name> given in SXML element
588{{obj}} or {{#f}} is such a node is absent.
589
590'''NOTE:''' it returns just the ''first'' node found even if multiple
591nodes are present, so it's mostly intended for nodes with unique names.
592Use {{sxml:aux-nodes}} if you want all of them.
593
594<procedure>(sxml:aux-nodes obj aux-name)</procedure>
595   
596Return a list of aux-nodes with {{aux-name}} given in SXML element
597{{obj}} or {{'()}} if such a node is absent.
598
599<procedure>(sxml:attr obj attr-name)</procedure>
600
601Returns the value of the attribute with name {{attr-name}} in the
602given SXML element {{obj}}, or {{#f}} if no such attribute exists.
603
604<procedure>(sxml:attr-from-list attr-list name)</procedure>
605
606Returns the value of the attribute with name {{attr-name}} in the
607given list of attributes {{attr-list}}, or {{#f}} if no such attribute
608exists.  The list of attributes can be obtained from an element using
609the {{sxml:attr-list}} procedure.
610
611<procedure>(sxml:num-attr obj attr-name)</procedure>
612
613Returns the value of the numerical attribute with name {{attr-name}}
614in the given SXML element {{obj}}, or {{#f}} if no such attribute
615exists.  This value is converted from a string to a number.
616
617<procedure>(sxml:attr-u obj attr-name)</procedure>
618
619Accessor for an attribute {{attr-name}} of given SXML element {{obj}},
620which may also be an attributes-list or a nodeset (usually content of
621an SXML element)
622
623<procedure>(sxml:ns-list obj)</procedure>
624
625Returns the list of namespaces for given element.  Analog of
626{{((sxpath '(@@ *NAMESPACES* *)) obj)}}.  The empty list is returned
627if there are no namespaces.
628
629<procedure>(sxml:ns-id->nodes obj namespace-id)</procedure>
630
631Returns a list of namespace information lists that match the given
632{{namespace-id}} in SXML element {{obj}}.  Analog of
633{{((sxpath '(@@ *NAMESPACES* namespace-id)) obj)}}.
634The empty list is returned if there is no namespace with the given
635{{namespace-id}}.
636
637<examples>
638<example>
639<expr>
640(sxml:ns-id->nodes
641  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")))) 'c)
642</expr>
643<result>((c "http://www.cars.com/xml"))</result>
644</example>
645</examples>
646
647<procedure>(sxml:ns-id->uri obj namespace-id)</procedure>
648
649Returns the URI for the (first) namespace matching the given
650{{namespace-id}}, or {{#f}} if no namespace matches the given
651{{namespace-id}}.
652
653<examples>
654<example>
655<expr>
656(sxml:ns-id->uri
657  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")))) 'c)
658</expr>
659<result>"http://www.cars.com/xml"</result>
660</example>
661</examples>
662
663<procedure>(sxml:ns-uri->nodes obj uri)</procedure>
664
665Returns a list of namespace information lists that match the given
666{{uri}} in SXML element {{obj}}.
667
668<examples>
669<example>
670<expr>
671(sxml:ns-uri->nodes
672  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")
673                                 (d "http://www.cars.com/xml"))))
674  "http://www.cars.com/xml")
675</expr>
676<result>((c "http://www.cars.com/xml") (d "http://www.cars.com/xml"))</result>
677</example>
678</examples>
679
680<procedure>(sxml:ns-uri->id obj uri)</procedure>
681
682Returns the namespace id for the (first) namespace matching the given
683{{uri}}, or {{#f}} if no namespace matches the given {{uri}}.
684
685<examples>
686<example>
687<expr>
688(sxml:ns-uri->id
689  '(c:part (@) (@@ (*NAMESPACES* (c "http://www.cars.com/xml")
690                                 (d "http://www.cars.com/xml"))))
691  "http://www.cars.com/xml")
692</expr>
693<result>c</result>
694</example>
695</examples>
696
697<procedure>(sxml:ns-id ns-list)</procedure>
698
699Given a namespace information list {{ns-list}}, returns the namespace ID.
700
701<procedure>(sxml:ns-uri ns-list)</procedure>
702
703Given a namespace information list {{ns-list}}, returns the namespace URI.
704
705<procedure>(sxml:ns-prefix ns-list)</procedure>
706
707Given a namespace information list {{ns-list}}, returns the namespace
708prefix if it is present in the list.  If it's not present, returns the
709namespace ID.
710
711==== Data modification procedures
712
713Constructors and mutators for normalized SXML data
714 
715'''Important:''' These functions are optimized for normalized SXML
716data.  They are ''not'' applicable to arbitrary non-normalized SXML
717data.
718
719Most of the functions are provided in two variants:
720
721# Side-effect intended functions for linear update of given elements.  Their names are ended with exclamation mark.
722# Pure functions without side-effects which return modified elements.
723
724
725<procedure>(sxml:change-content! obj new-content)</procedure>
726<procedure>(sxml:change-content obj new-content)</procedure>
727
728Change the content of given SXML element {{obj}} to {{new-content}}.
729If {{new-content}} is an empty list then the {{obj}} is transformed to
730an empty element.  The resulting SXML element is normalized.
731
732<procedure>(sxml:change-attrlist obj new-attrlist)</procedure>
733<procedure>(sxml:change-attrlist! obj new-attrlist)</procedure>
734
735Change the attribute list of the given SXML element {{obj}} to
736{{new-attrlist}}.
737
738<procedure>(sxml:change-name obj new-name)</procedure>
739<procedure>(sxml:change-name! obj new-name)</procedure>
740
741Change the name of the given SXML element {{obj}} to {{new-name}}.
742
743<procedure>(sxml:add-attr obj attr)</procedure>
744<procedure>(sxml:add-attr! obj attr)</procedure>
745
746Returns the given SXML element {{obj}} with the attribute {{attr}}
747added to the attribute list, or {{#f}} if the attribute already exists.
748
749<procedure>(sxml:change-attr obj attr)</procedure>
750<procedure>(sxml:change-attr! obj attr)</procedure>
751
752Returns SXML element {{obj}} with changed value of attribute {{attr}}
753or {{#f}} if where is no attribute with given name.
754
755{{attr}} is a list like it would occur as a member of an attribute
756list: {{(attr-name attr-value)}}.
757   
758<procedure>(sxml:set-attr obj attr)
759<procedure>(sxml:set-attr! obj attr)
760
761Returns SXML element {{obj}} with changed value of attribute {{attr}}.
762If there is no such attribute the new one is added.
763
764{{attr}} is a list like it would occur as a member of an attribute
765list: {{(attr-name attr-value)}}.
766
767<procedure>(sxml:add-aux obj aux-node)</procedure>
768<procedure>(sxml:add-aux! obj aux-node)</procedure>
769
770Returns SXML element {{obj}} with an auxiliary node {{aux-node}} added.
771
772<procedure>(sxml:squeeze obj)</procedure>
773<procedure>(sxml:squeeze! obj)</procedure>
774
775Returns a minimized and normalized SXML element {{obj}} with empty
776lists of attributes and aux-lists eliminated, in {{obj}} and all its
777descendants.
778   
779<procedure>(sxml:clean obj)</procedure>
780
781Returns a minimized and normalized SXML element {{obj}} with empty
782lists of attributes and '''all''' aux-lists eliminated, in {{obj}} and
783all its descendants.
784
785
786==== Sxpath-related procedures
787
788<procedure>(select-first-kid test-pred?)</procedure>
789
790Given a node, return the first child that satisfies the
791{{test-pred?}}.  Given a nodeset, traverse the set until a node is
792found whose first child matches the predicate.  Returns {{#f}} if
793there is no such a child to be found.
794
795<procedure>(sxml:node-parent rootnode)</procedure>
796
797Returns a function of one argument - an SXML element - which returns
798its parent node using {{*PARENT*}} pointer in the aux-list.
799{{'*TOP-PTR*}} may be used as a pointer to root node.  It returns an
800empty list when applied to the root node.
801
802<procedure>(sxml:add-parents obj [top-ptr])</procedure>
803
804Returns the SXML element {{obj}} annotated with {{*PARENT*}} pointers
805for {{obj}} and all its descendants.  If {{obj}} is not the root node
806(a node with a name of {{*TOP*}}), you must pass in the parent pointer
807for {{obj}} as {{top-ptr}}.
808
809'''Warning:''' This procedure mutates its {{obj}} argument.
810
811<procedure>(sxml:lookup id index)</procedure>
812
813Lookup an element using its ID.  {{index}} should be an alist of
814{{(id . element)}}.
815
816==== Markup generation
817
818===== XML
819
820<procedure>(sxml:attr->xml attr)</procedure>
821
822Returns a list containing tokens that when joined together form the
823attribute's XML output.
824
825'''Warning:''' This procedure assumes that the attribute's values have
826already been escaped (ie, {{sxml:string->xml has been called on the
827strings inside it}}).
828
829<examples>
830<example>
831<expr>(sxml:attr->xml '(href "http://example.com"))</expr>
832<result>(" " "href" "='" "http://example.com" "'")</result>
833</example>
834</examples>
835
836<procedure>(sxml:string->xml string)</procedure>
837
838Escape the {{string}} so it can be used anywhere in XML output.  This
839converts the {{<}}, {{>}}, {{'}}, {{"}} and {{&}} characters to their
840respective entities.
841
842<procedure>(sxml:sxml->xml tree)</procedure>
843
844Convert the {{tree}} of SXML nodes to a nested list of XML fragments.
845These fragments can be output by flattening the list and concatenating
846the strings inside it.
847
848==== HTML
849
850<procedure>(sxml:attr->html attr)</procedure>
851
852Returns a list containing tokens that when joined together form the
853attribute's HTML output.  The difference with the XML variant is that
854this encodes empty attribute values to attributes with no value (think
855{{selected}} in option elements, or {{checked}} in checkboxes).
856
857'''Warning:''' This procedure assumes that the attribute's values have
858already been escaped (ie, {{sxml:string->html has been called on the
859strings inside it}}).
860
861<procedure>(sxml:string->html string)</procedure>
862
863Escape the {{string}} so it can be used anywhere in XML output.  This
864converts the {{<}}, {{>}}, {{"}} and {{&}} characters to their
865respective entities.
866
867<procedure>(sxml:non-terminated-html-tag? tag)</procedure>
868
869Is the named {{tag}} one that is "self-closing" (ie, does not need to
870be terminated) in HTML 4.0?
871
872<procedure>(sxml:sxml->html tree)</procedure>
873
874Convert the {{tree}} of SXML nodes to a nested list of HTML fragments.
875These fragments can be output by flattening the list and concatenating
876the strings inside it.
877
878
879=== Procedures from sxpathlib
880
881==== Basic converters and applicators
882
883A converter is a function
884
885  type Converter = Node|Nodelist -> Nodelist
886
887A converter can also play a role of a predicate: in that case, if a
888converter, applied to a node or a nodelist, yields a non-empty
889nodelist, the converter-predicate is deemed satisfied. Throughout this
890file a nil nodelist is equivalent to {{#f}} in denoting a failure.
891
892<procedure>(nodeset? obj)</procedure>
893
894Returns {{#t}} if {{obj}} is a nodelist.
895
896<procedure>(as-nodeset obj)</procedure>
897
898If {{obj}} is a nodelist - returns it as is, otherwise wrap it in a
899list.
900
901==== Node test
902
903The following functions implement 'Node test's as defined in Sec. 2.3
904of the XPath document.  A node test is one of the components of a
905location step.  It is also a converter-predicate in SXPath.
906
907<procedure>(sxml:element? obj)</procedure>
908
909Predicate which returns {{#t}} if {{obj}} is SXML element, otherwise {{#f}}.
910
911<procedure>(ntype-names?? crit)</procedure>
912
913Takes a list of acceptable node names as a criterion and returns a
914function, which, when applied to a node, will return {{#t}} if the
915node name is present in criterion list and {{#f}} otherwise.
916
917   ntype-names?? :: ListOfNames -> Node -> Boolean
918
919<procedure>(ntype?? crit)</procedure>
920
921Takes a type criterion and returns a function, which, when applied to
922a node, will tell if the node satisfies the test.
923
924  ntype?? :: Crit -> Node -> Boolean
925
926The criterion {{crit}} is  one of the following symbols:
927
928; {{@}} : tests if the Node is an {{attributes-list}}
929; {{*}} : tests if the Node is an {{Element}}
930; {{*text*}} : tests if the Node is a text node
931; {{*data*}} : tests if the Node is a data node  (text, number, boolean, etc., but not pair)
932; {{*PI*}} : tests if the Node is a processing instructions node
933; {{*COMMENT*}} : tests if the Node is a comment node
934; {{*ENTITY*}} : tests if the Node is an entity node
935; {{*any*}} : {{#t}} for any type of Node
936; other symbol : tests if the Node has the right name given by the symbol
937
938<examples>
939<example>
940<expr>
941((ntype?? 'div) '(div (@ (class "greeting")) "hi"))
942</expr>
943<result>
944#t
945</result>
946</example>
947<example>
948<expr>
949((ntype?? 'div) '(span (@ (class "greeting")) "hi"))
950</expr>
951<result>
952#f
953</result>
954</example>
955<example>
956<expr>
957((ntype?? '*) '(span (@ (class "greeting")) "hi"))
958</expr>
959<result>
960#t
961</result>
962</example>
963</examples>
964   
965<procedure>(ntype-namespace-id?? ns-id)</procedure>
966
967This function takes a namespace-id, and returns a predicate
968{{Node -> Boolean}}, which is {{#t}} for nodes with the given
969namespace id. {{ns-id}} is a string.
970{{(ntype-namespace-id?? #f)}} will be {{#t}} for nodes with
971non-qualified names.
972
973<procedure>(sxml:complement pred)</procedure>
974
975This function takes a predicate and returns it complemented, that is
976if the given predicate yields {{#f}} or {{'()}} the complemented one
977yields the given node and vice versa.
978
979<procedure>(node-eq? other)</procedure>
980
981Returns a predicate procedure that, given a node, returns {{#t}} if
982the node is the exact same as {{other}}.
983
984<procedure>(node-equal? other)</procedure>
985
986Returns a predicate procedure that, given a node, returns {{#t}} if
987the node has the same contents as {{other}}.
988
989<procedure>(node-pos n)</procedure>
990
991Returns a procedure that, given a nodelist, returns a new nodelist
992containing only the {{n}}th element, counting from 1.  If {{n}} is
993negative, it returns a nodelist with the {{n}}th element counting from
994the right.  If no such node exists, returns the empty list.  {{n}} may
995not equal zero.
996
997<examples>
998<example>
999<expr>
1000((node-pos 1) '((div "hi") (span "hello") (em "really, hi!")))
1001</expr>
1002<result>
1003((div "hi"))
1004</result>
1005</example>
1006<example>
1007<expr>
1008((node-pos 6) '((div "hi") (span "hello") (em "really, hi!")))
1009</expr>
1010<result>
1011()
1012</result>
1013</example>
1014<example>
1015<expr>
1016((node-pos -1) '((div "hi") (span "hello") (em "is this thing on?")))
1017</expr>
1018<result>
1019((em "is this thing on?"))
1020</result>
1021</example>
1022</examples>
1023
1024<procedure>(sxml:filter pred?)</procedure>
1025
1026Returns a procedure that accepts a nodelist or a node (which will be
1027converted to a one-element nodelist) and returns only those nodes for
1028which the predicate {{pred?}} does not return {{#f}} or {{'()}}.
1029
1030<examples>
1031<example>
1032<expr>
1033((sxml:filter (ntype?? 'div)) '((div "hi") (span "hello") (div "still here?")))
1034</expr>
1035<result>
1036((div "hi") (div "still here?"))
1037</result>
1038</example>
1039</examples>
1040
1041<procedure>(take-until pred?)</procedure>
1042<procedure>(take-after pred?)</procedure>
1043
1044Returns a procedure that accepts a node or a nodelist.
1045
1046The {{take-until}} variant returns everything ''before'' the first
1047node for which the predicate {{pred?}} returns anything but {{#f}} or
1048{{'()}}.  In other words, it returns the longest prefix for which the
1049predicate returns {{#f}} or {{'()}}.
1050
1051The {{take-after}} variant returns everything ''after'' the first node
1052for which the predicate {{pred?}} returns anything besides {{#f}} or
1053{{'()}}.
1054
1055<examples>
1056<example>
1057<expr>
1058((take-until (ntype?? 'span)) '((div "hi") (span "hello") (span "there") (div "still here?")))
1059</expr>
1060<result>
1061((div "hi"))
1062</result>
1063</example>
1064<example>
1065<expr>
1066((take-after (ntype?? 'span)) '((div "hi") (span "hello") (span "there") (div "still here?")))
1067</expr>
1068<result>
1069((span "there") (div "still here?"))
1070</result>
1071</example>
1072</examples>
1073
1074<procedure>(map-union proc list)</procedure>
1075
1076Apply {{proc}} to each element of the nodelist {{lst}} and return the
1077list of results.  If {{proc}} returns a nodelist, splice it into the
1078result (essentially returning a flattened nodelist).
1079
1080<procedure>(node-reverse node-or-nodelist)</procedure>
1081
1082Accepts a nodelist and reverses the nodes inside.  If a node is passed
1083to this procedure, it returns a nodelist containing just that node.
1084(it does not change the order of the children).
1085
1086==== Converter combinators
1087
1088Combinators are higher-order functions that transmogrify a converter
1089or glue a sequence of converters into a single, non-trivial
1090converter. The goal is to arrive at converters that correspond to
1091XPath location paths.
1092
1093From a different point of view, a combinator is a fixed, named
1094''pattern'' of applying converters. Given below is a complete set of
1095such patterns that together implement XPath location path
1096specification. As it turns out, all these combinators can be built
1097from a small number of basic blocks; regular functional composition,
1098{{map-union}} and filter applicators, and the nodelist union.
1099
1100<procedure>(select-kids pred?)</procedure>
1101
1102Returns a procedure that accepts a node and returns a nodelist of the
1103node's children that satisfy {{pred?}} (ie, {{pred?}} returns anything
1104but {{#f}} or {{'()}}).
1105
1106<procedure>(node-self pred?)</procedure>
1107
1108Similar to {{select-kids}} but applies to the node itself rather than
1109to its children. The resulting Nodelist will contain either one
1110component (the node), or will be empty (if the node failed the
1111predicate).
1112
1113<procedure>(node-join . selectors)</procedure>
1114
1115Returns a procedure that accepts a nodelist or a node, and returns a
1116nodelist with all the selectors applied to every node in sequence.
1117The selectors must function as converter combinators, ie they must
1118accept a ''node'' and output a ''nodelist''.
1119
1120<examples>
1121<example>
1122<expr>
1123((node-join
1124  (select-kids (ntype?? 'li))
1125  sxml:content)
1126 '((ul (@ (class "whiskies"))
1127       (li "Ardbeg")
1128       (li "Glenfarclas")
1129       (li "Springbank"))))
1130</expr>
1131<result>
1132("Ardbeg" "Glenfarclas" "Springbank")
1133</result>
1134</example>
1135</examples>
1136
1137<procedure>(node-reduce . converters)</procedure>
1138
1139A regular functional composition of converters.
1140
1141From a different point of view,
1142  ((apply node-reduce converters) nodelist)
1143is equivalent to
1144  (fold apply nodelist converters)
1145i.e., folding, or reducing, a list of converters with the nodelist
1146as a seed.
1147
1148
1149<procedure>(node-or . converters)</procedure>
1150
1151This combinator applies all converters to a given node and produces
1152the union of their results.  This combinator corresponds to a union,
1153"{{|}}" operation for XPath location paths.
1154
1155<procedure>(node-closure test-pred?)</procedure>
1156
1157Select all ''descendants'' of a node that satisfy a
1158converter-predicate.  This combinator is similar to {{select-kids}}
1159but applies to grandchildren as well.
1160
1161<procedure>(node-trace title)</procedure>
1162
1163Returns a procedure that accepts a node or a nodelist, which it
1164pretty-prints to the current output port, preceded by {{title}}.  It
1165returns the node or the nodelist unchanged.  This is a useful
1166debugging aid, since it doesn't really do anything besides print its
1167argument and pass it on.
1168
1169<procedure>(sxml:node? obj)</procedure>
1170
1171Returns {{#t}} if the given {{obj}} is an SXML node, {{#f}} otherwise.
1172A node is anything except an attribute list or an auxiliary list.
1173
1174<procedure>(sxml:attr-list node)</procedure>
1175
1176Returns the list of attributes for a given SXML node.  The empty list
1177is returned if the given node is not an element, or if it has no list
1178of attributes.
1179
1180This differs from {{sxml:attr-list-u}} in that this procedure accepts
1181any SXML node while {{sxml:attr-list-u}} only accepts nodelists or
1182elements.  This means that sxml:attr-list-u will throw an error if you
1183pass it a text node (a string), while sxml:attr-list will not.
1184
1185<procedure>(sxml:attribute test-pred?)</procedure>
1186
1187Like {{sxml:filter}}, but considers the attributes instead of the
1188nodes.  Returns a nodelist of attribtes that match {{test-pred?}}.
1189
1190<examples>
1191<example>
1192<expr>
1193((sxml:attribute (ntype?? 'id))
1194 '((div (@ (id "navigation")) "navigation here")
1195   (div (@ (class "pullquote")) "random stuff")
1196   (div (@ (id "main-content")) "lorem ipsum ...")))
1197</expr>
1198<result>
1199((id "navigation") (id "main-content"))
1200</result>
1201</example>
1202</examples>
1203
1204<procedure>(sxml:child test-pred?)</procedure>
1205
1206This procedure is similar to {{select-kids}}, but it returns an empty
1207child-list for PI, Comment and Entity nodes.
1208
1209<procedure>(sxml:parent test-pred?)</procedure>
1210
1211Returns a procedure that accepts a root-node, and returns another
1212procedure.  This second procedure accepts a nodeset (or a node) and
1213returns the immediate parents of the nodes in the set, but only if
1214for those parents that match the predicate.
1215
1216The root-node does not have to be the root node of the
1217whole SXML tree -- it may be a root node of a branch of interest.
1218
1219This procedure can be used with any SXML node.
1220
1221==== Useful shortcuts
1222
1223<procedure>(node-parent node)</procedure>
1224
1225{{(node-parent rootnode)}} yields a converter that returns a parent of a
1226node it is applied to. If applied to a nodelist, it returns the list
1227of parents of nodes in the nodelist.
1228
1229This is equivalent to {{((sxml:parent (ntype? '*any*)) node)}}.
1230
1231<procedure>(sxml:child-nodes node)</procedure>
1232
1233Returns all the child nodes of the given {{node}}.
1234
1235This is equivalent to {{((sxml:child sxml:node?) node)}}.
1236
1237<procedure>(sxml:child-elements node)</procedure>
1238
1239Returns all the child ''elements'' of the given {{node}}. (ie,
1240excludes any textnodes).
1241
1242This is equivalent to {{((select-kids sxml:element?) node)}}.
1243
1244=== Procedures from sxpath-ext
1245
1246==== SXML counterparts to W3C XPath Core Functions Library
1247
1248<procedure>(sxml:string object)</procedure>
1249
1250The counterpart to XPath 'string' function (section 4.2 XPath 1.0 Rec.).
1251Converts a given object to a string.
1252
1253Notes:
1254# When converting a nodeset, document order is not preserved
1255# {{number->string}} returns the result in a form which is slightly different from XPath Rec. specification
1256
1257<procedure>(sxml:boolean object)</procedure>
1258
1259The counterpart to XPath 'boolean' function (section 4.3 XPath Rec.).
1260Converts its argument to a boolean.
1261
1262<procedure>(sxml:number object)</procedure>
1263
1264The counterpart to XPath 'number' function (section 4.4 XPath Rec.).
1265Converts its argument to a number.
1266
1267Notes:
1268# The argument is not optional (yet?)
1269# string->number conversion is not IEEE 754 round-to-nearest
1270# NaN is represented as 0
1271
1272<procedure>(sxml:string-value node)</procedure>
1273
1274Returns a string value for a given node in accordance to
1275XPath Rec. 5.1 - 5.7
1276
1277<procedure>(sxml:id id-index)</procedure>
1278
1279Returns a procedure that accepts a nodeset and returns a nodeset
1280containing the elements in the id-index that match the string-values
1281of each entry of the nodeset.  XPath Rec. 4.1
1282
1283The {{id-index}} is an alist with unique IDs as key, and elements as
1284values:
1285
1286  id-index = ( (id-value . element) (id-value . element) ... )
1287
1288==== Comparators for XPath objects
1289
1290<procedure>(sxml:list-head list n)</procedure>
1291
1292Returns the {{n}} first members of {{list}}.  Mostly equivalent to
1293SRFI-1's {{take}} procedure, except it returns the {{list}} if {{n}}
1294is larger than the length of said list, instead of throwing an error.
1295
1296<procedure>(sxml:merge-sort less-than? list)</procedure>
1297
1298Returns the sorted list, the smallest member first.
1299  less-than? ::= (lambda (obj1 obj2) ...)
1300{{less-than?}} returns {{#t}} if {{obj1 < obj2}} with respect to the
1301given ordering.
1302
1303<procedure>(sxml:equality-cmp bool=? number=? string=?)</procedure>
1304
1305A helper for XPath equality operations: {{=}} , {{!=}}.  The
1306{{bool=?}}, {{number=?}} and {{string=?}} arguments are comparison
1307operations for booleans, numbers and strings respectively.
1308
1309Returns a procedure that accepts two objects, looks at the first
1310object's type and applies the correct comparison predicate to it.
1311Type coercion takes place depending on the rules described in the
1312XPath 1.0 spec, section 3.4 ("Booleans").
1313
1314<procedure>(sxml:equal? obj1 obj2)</procedure>
1315<procedure>(sxml:not-equal? obj1 obj2)</procedure>
1316
1317Equality procedures with the default comparison operators {{eq?}},
1318{{=}} and {{string=?}}, or their inverse, respectively.
1319
1320<procedure>(sxml:relational-cmp op)</procedure>
1321
1322A helper for XPath relational operations: {{<}}, {{>}}, {{<=}}, {{>=}}
1323for two XPath objects.  {{op}} is one of these operators.
1324
1325Returns a procedure that accepts two objects and returns the value of
1326the procedure applied to these objects, converted according to the
1327coercion rules described in the XPath 1.0 spec, section 3.4
1328("Booleans").
1329
1330==== XPath axes
1331
1332<procedure>(sxml:ancestor test-pred?)</procedure>
1333
1334Like {{sxml:parent}}, except it returns all the ancestors that match
1335{{test-pred?}}, not just the immediate parent.
1336
1337<procedure>(sxml:ancestor-or-self test-pred?)</procedure>
1338
1339Like {{sxml:ancestor}}, except also allows the node itself to match
1340the predicate.
1341
1342<procedure>(sxml:descendant test-pred?)</procedure>
1343
1344Like {{node-closure}}, except the resulting nodeset is in depth-first
1345order instead of breadth-first.
1346
1347<procedure>(sxml:descendant-or-self test-pred?)</procedure>
1348
1349Like {{sxml:descendant}}, except also allows the node itself to match
1350the predicate.
1351
1352<procedure>(sxml:following test-pred?)</procedure>
1353
1354Returns a procedure that accepts a root node and returns a new
1355procedure that accepts a node and returns all nodes following this
1356node in the document source matching the predicate.
1357
1358<procedure>(sxml:following-sibling test-pred?)</procedure>
1359
1360Like {{sxml:following}}, except only siblings (nodes at the same level
1361under the same parent) are returned.
1362
1363<procedure>(sxml:preceding test-pred?)</procedure>
1364
1365Returns a procedure that accepts a root node and returns a new
1366procedure that accepts a node and returns all nodes preceding this
1367node in the document source matching the predicate.
1368
1369<procedure>(sxml:preceding-sibling test-pred?)</procedure>
1370
1371Like {{sxml:preceding}}, except only siblings (nodes at the same level
1372under the same parent) are returned.
1373
1374<procedure>(sxml:namespace test-pred?)</procedure>
1375
1376Returns a procedure that accepts a nodeset and returns the namespace
1377lists of the nodes matching {{test-pred?}}.
1378
1379
1380== About this egg
1381
1382=== Author
1383
1384[[http://okmij.org/ftp/|Oleg Kiselyov]], [[http://www196.pair.com/lisovsky/|Kirill Lisovsky]], [[http://modis.ispras.ru/Lizorkin/index.html|Dmitry Lizorkin]].
1385
1386=== Version history
1387
1388; 0.1 : Split up the old sxml-tools egg into sxpath
1389
1390=== License
1391
1392The sxml-tools are in the public domain.
Note: See TracBrowser for help on using the repository browser.