Automatically Generated Documentation

S X M L   T o o l s

Swiss Army Knife  
for SXML data    


Predicates
f: sxml:node?
f: sxml:element?
f: sxml:empty-element?
f: sxml:void-element?
f: sxml:shallow-normalized?

Accessors
f: sxml:name
f: sxml:element-name
f: sxml:node-name
f: sxml:content
f: sxml:attr-content
f: sxml:child-elements
f: sxml:attr-list
f: sxml:attr

Data modification functions
f: sxml:content!
f: sxml:attrlist!
f: sxml:name!
f: sxml:add-attr!
f: sxml:set-attr!
f: sxml:attr!
f: sxml:append-content!
f: sxml:insert-unique!
f: sxml:normalize!
f: sxml:squeeze!

SXPath-related
extensions
f: node-typeof-list?
f: map-on-type
wrappers
f: if-sxpath
f: if-car-sxpath
f: car-sxpath

Predicates


sxml:node?

(define (sxml:node? obj)
... Full Code ... )
Predicate which returns #t if <obj> is SXML node, otherwise returns #f. 


sxml:element?

(define (sxml:element? obj)
... Full Code ... )
Predicate which returns #t if <obj> is SXML element, otherwise returns #f. 


sxml:empty-element?

(define (sxml:empty-element? obj)
... Full Code ... )
Predicate which returns #t if given element <obj> is empty. 
Empty element has no content but may contain some attributes.
It is a counterpart of XML empty-element.


sxml:void-element?

(define (sxml:void-element? obj)
... Full Code ... )
Predicate which returns #t if given element <obj> is void.
Void element has neither content nor attributes, namespaces or comments,
So, the every void element is also the empty one.


sxml:shallow-normalized?

(define (sxml:shallow-normalized? obj)
... Full Code ... )
Returns #t if the given <obj> is shallow-normalized SXML element.
This means that this element itself has a list of attributes
in the second position, but it doesn't  test its nested elements.



Accessors


sxml:name

(define sxml:name
... Full Code ... )
Returns a name of the given element
Sample call: (sxml:name element)
It is introduced for the sake of encapsulation.


sxml:element-name

(define (sxml:element-name obj)
... Full Code ... )
Safe version of sxml:name, which returns #f if the given <obj> is 
not a SXML element.
Otherwise returns its name.


sxml:node-name

(define (sxml:node-name obj)
... Full Code ... )
Safe version of sxml:name, which returns #f if the given <obj> is 
not a SXML node.
Otherwise returns its name.


sxml:content

(define (sxml:content obj)
... Full Code ... )
Returns the content of given SXML element, representing it
as a list of values and nested elements in document (depth-first) order. 
This list is empty for an empty element.
<obj> is minimized or normalized SXML element.


sxml:attr-content

(define (sxml:attr-content obj)
... Full Code ... )
Returns the list whose car is the list of attributes for given <obj>
and whose cdr is the content of given <obj>
<obj> is minimized or normalized SXML element


sxml:child-elements

(define (sxml:child-elements obj)
... Full Code ... )
Returns a list of all the children elements for the given <obj>,
<obj> which have to be minimized or normalized SXML element


sxml:attr-list

(define (sxml:attr-list obj)
... Full Code ... )
Returns the list of attributes for the given element.
Analog of ((sxpath '(@ *)) obj)
Empty list is returned if there is no attributes for the element.


sxml:attr

(define (sxml:attr obj attr-name)
... Full Code ... )
Accessor for the attribute named <attr-name> for the given SXML element
<obj> which may also be an  attributes-list

Analog of ((if-car-sxpath '(@ attr-name *text*)) obj)

It returns: 
the value of the attribute if the attribute is present and has a value
#f if there is no such an attribute in the given element
attribute name (as a string) if the attribute is singular (boolean)



Data modification functions

Constructors and mutators

sxml:content!

(define (sxml:content! obj new-content)
... Full Code ... )
if the <new-content> is an empty list then the <obj> is transformed 
to an empty element
The resulting SXML element is normalized


sxml:attrlist!

(define (sxml:attrlist! obj new-attrlist)
... Full Code ... )
Ground function for attribute manipulations
The resulting SXML element is normalized, if <new-attrlist> is empty,
the cadr of <obj> is (@)


sxml:name!

(define (sxml:name! obj new-name)
... Full Code ... )
Change name of a SXML element


sxml:add-attr!

(define (sxml:add-attr! obj attr-name attr-value)
... Full Code ... )
Add an attribute <attr-name> with a value <attr-value> for an element 
<obj>
Returns #f if the attribute with given name already exists, 
or the modified SXML node in case of success
The resulting SXML node is normalized


sxml:set-attr!

(define (sxml:set-attr! obj attr-name attr-value)
... Full Code ... )
Set value of the attribute <attr-name> of element <obj> to <attr-value>
Returns #f if there is no such attribute, or the modified SXML element 
in case of success
The resulting SXML element is normalized


sxml:attr!

(define (sxml:attr! obj attr-name attr-value)
... Full Code ... )
Set the value of the attribute <attr-name> of element <obj> to <attr-value>
If there is no such attribute the new one is added
Returns: the SXML element modified 


sxml:append-content!

(define (sxml:append-content! obj . new-data)
... Full Code ... )
Appends <new-data> to the content of the <obj>
The resulting SXML element is normalized


sxml:insert-unique!

(define (sxml:insert-unique! obj element)
... Full Code ... )
This function inserts new sub-elements in sxml node <obj>
if there is no elements with the same name yet
<element> is a sxml element to insert

Absolete name: if-insert-node!


sxml:normalize!

(define (sxml:normalize! obj)
... Full Code ... )
Normalize SXML data structure for the given <obj> and its descendants
Returns: normalized SXML element


sxml:squeeze!

(define (sxml:squeeze! obj)
... Full Code ... )
Eliminates empty lists of attributes for the given SXML element 
<obj> and its descendants ("minimize" it)
Returns: minimized SXML element



SXPath-related



extensions


node-typeof-list?

(define (node-typeof-list? crit)
... Full Code ... )
The function node-typeof-list? takes a type criterion and returns
a function, which, when applied to a node, will tell if the node satisfies
the test.
	node-typeof? :: Crit -> Node -> Boolean

The criterion 'crit' is 
one of the following symbols:
	id		- tests if the Node has the right name (id)
	@		- tests if the Node is an <attributes-coll>
	*		- tests if the Node is an <Element>
	*text*		- tests if the Node is a text node
	*data*		- tests if the Node is a data node 
(text, number, boolean, etc)
	*PI*		- tests if the Node is a PI node
	*any*		- #t for any type of Node
or list of symbols
	(id ...)	- tests if the Node has the right name, 
listed in (id ...) list


map-on-type

(define (map-on-type . handlers)
... Full Code ... )
Map children elements of the given nodeset using corresponding
handlers for subnodes in accordance to their types.
Each handler is a pair whose car is a tag name and cdr is a function 
of one argument to apply.
If an element has a type which is supported by one of handlers then
it is mapped using the function of this handler. 
If where is no handler for some element then it is omitted from the result.

Sample call
((map-on-type `(tag . ,tag-handler)
	 `(tag1 . ,tag1-handler)) c)



wrappers


if-sxpath

(define (if-sxpath path)
... Full Code ... )
sxpath always returns a list, which is #t in Scheme 
if-sxpath returns #f instead of empty list


if-car-sxpath

(define (if-car-sxpath path)
... Full Code ... )
Returns first node found, if any.
Otherwise returns #f.


car-sxpath

(define (car-sxpath path)
... Full Code ... )
Returns first node found, if any.
Otherwise returns empty list.


Code

sxml:node?
Index
Predicate which returns #t if <obj> is SXML node, otherwise returns #f. 
(define (sxml:node? obj)	
  (and                            ; The object is SXML node if:
       (list? obj)                ; - it is a list and
       (not (null? obj))          ; - it is not empty
       (symbol? (car obj))        ; - its car is symbol
       ))

sxml:element?
Index
Predicate which returns #t if <obj> is SXML element, otherwise returns #f. 
(define (sxml:element? obj)	
  (and                            ; The object is SXML element if:
       (list? obj)                ; - it is a list and
       (not (null? obj))          ; - it is not empty
       (symbol? (car obj))        ; - its car is symbol (name)
       (not (member (car obj) 
	     '(@                  ; - it is not a list of attributes, etc.
		*TOP* 		  
		*PI*
		*COMMENT* 
		*ENTITY*
		*NAMESPACES*)))))


sxml:empty-element?
Index
Predicate which returns #t if given element <obj> is empty. 
Empty element has no content but may contain some attributes.
It is a counterpart of XML empty-element.
(define (sxml:empty-element? obj)
  (and (sxml:element? obj)
       (null? (sxml:content obj))))

sxml:void-element?
Index
Predicate which returns #t if given element <obj> is void.
Void element has neither content nor attributes, namespaces or comments,
So, the every void element is also the empty one.
(define (sxml:void-element? obj)
  (and 
    (sxml:element? obj)
    (or 
      (null? (cdr obj)) 
      (and 
	(eq? '@ (cadr obj)) 
	(null? (cdadr obj)) 
	(null? (cddr obj))))))


sxml:shallow-normalized?
Index
Returns #t if the given <obj> is shallow-normalized SXML element.
This means that this element itself has a list of attributes
in the second position, but it doesn't  test its nested elements.
(define (sxml:shallow-normalized? obj)
  (and 
    (sxml:element? obj)
    (not 
      (null? (cdr obj))) 
    (list? (cadr obj)) 
    (eq? (car (cadr obj)) 
	 '@)))


sxml:name
Index
Returns a name of the given element
Sample call: (sxml:name element)
It is introduced for the sake of encapsulation.
(define sxml:name car)

sxml:element-name
Index
Safe version of sxml:name, which returns #f if the given <obj> is 
not a SXML element.
Otherwise returns its name.
(define (sxml:element-name obj)
  (if (sxml:element? obj)
    (car obj)
    #f))

sxml:node-name
Index
Safe version of sxml:name, which returns #f if the given <obj> is 
not a SXML node.
Otherwise returns its name.
(define (sxml:node-name obj)
  (if (sxml:node? obj)
    (car obj)
    #f))

sxml:content
Index
Returns the content of given SXML element, representing it
as a list of values and nested elements in document (depth-first) order. 
This list is empty for an empty element.
<obj> is minimized or normalized SXML element.
(define (sxml:content obj)
  ((select-kids (node-typeof-list? '(* *text*))) obj))
  

sxml:attr-content
Index
Returns the list whose car is the list of attributes for given <obj>
and whose cdr is the content of given <obj>
<obj> is minimized or normalized SXML element
(define (sxml:attr-content obj)
  (let rpt ((cl (cdr obj)) (cn '()))
    (if (null? cl)
       (cons '(@) cn)
      ((lambda (h)
	 (if (and (list? h)
		  (eq? (car h) '@))
	   (cons h (append cn (cdr cl)))
	   (rpt (cdr cl) (append cn (list h))))) 
       (car cl)))))

sxml:child-elements
Index
Returns a list of all the children elements for the given <obj>,
<obj> which have to be minimized or normalized SXML element
(define (sxml:child-elements obj)
  (let rpt ((ns obj)
	    (rez '()))
    (if (null? ns)
      rez
      (rpt (cdr ns) 
	   (if (sxml:element? (car ns))
	     (cons (car ns) rez) 
	     rez)))))
	   
sxml:attr-list
Index
Returns the list of attributes for the given element.
Analog of ((sxpath '(@ *)) obj)
Empty list is returned if there is no attributes for the element.
(define (sxml:attr-list obj)
  (let rpt ((cl (cdr obj)))
    (if (null? cl)
      '()
	 (if (and (pair? (car cl))
		  (eq? (caar cl) '@))
	   (cdar cl)
	   (rpt (cdr cl)))) 
       ))


sxml:attr
Index
Accessor for the attribute named <attr-name> for the given SXML element
<obj> which may also be an  attributes-list

Analog of ((if-car-sxpath '(@ attr-name *text*)) obj)

It returns: 
the value of the attribute if the attribute is present and has a value
#f if there is no such an attribute in the given element
attribute name (as a string) if the attribute is singular (boolean)
(define (sxml:attr obj attr-name)
  (cond 
    ((assv attr-name 
	   (cond
	     ((and (not (null? (cdr obj))) 
		   (list? (cadr obj))
		   (eq? '@ (caadr obj)))
	      (cdadr obj))   ; fast track for normalized elements 
	     ((eq? '@ (car obj))
	     (cdr obj))
	     (else
	     (sxml:attr-list obj)))) => 
					   (lambda(x)
					     (if (null? (cdr x))
					       (symbol->string attr-name)
					       (cadr x))))
    (else #f)))

sxml:content!
Index
if the <new-content> is an empty list then the <obj> is transformed 
to an empty element
The resulting SXML element is normalized
(define (sxml:content! obj new-content)
  (set-cdr! obj (cons 
			 (cons '@ (sxml:attr-list obj)) 
			     new-content))
  obj)

sxml:attrlist!
Index
Ground function for attribute manipulations
The resulting SXML element is normalized, if <new-attrlist> is empty,
the cadr of <obj> is (@)
(define (sxml:attrlist! obj new-attrlist)
       (set-cdr! obj 
		 (cons
			(cons '@ new-attrlist) 
			(sxml:content obj)))
       obj) 
       
sxml:name!
Index
Change name of a SXML element
(define (sxml:name! obj new-name)
  (set-car! obj new-name)
  obj)

sxml:add-attr!
Index
Add an attribute <attr-name> with a value <attr-value> for an element 
<obj>
Returns #f if the attribute with given name already exists, 
or the modified SXML node in case of success
The resulting SXML node is normalized
(define (sxml:add-attr! obj attr-name attr-value)
  (let ((x (sxml:attr-list obj)))
    (cond
      ((null? x)
       (set-cdr! obj (cons 
			(list '@ (list  attr-name attr-value)) 
			(sxml:content obj)))
       obj)
      ((assv attr-name x)
       #f)
      (else
	(set-car! (cdr obj) 
		  (append (list '@ (list attr-name attr-value)) x))
	obj))))

sxml:set-attr!
Index
Set value of the attribute <attr-name> of element <obj> to <attr-value>
Returns #f if there is no such attribute, or the modified SXML element 
in case of success
The resulting SXML element is normalized
(define (sxml:set-attr! obj attr-name attr-value)
  (let ((x (sxml:attr-list obj)))
     (if (null? x)
       #f
       (cond 
	 ((assv attr-name x) => (lambda (y)
				  (set-car! (cdr y) attr-value) obj))
	 (else #f)))))

sxml:attr!
Index
Set the value of the attribute <attr-name> of element <obj> to <attr-value>
If there is no such attribute the new one is added
Returns: the SXML element modified 
(define (sxml:attr! obj attr-name attr-value)
  ((lambda (x)
     (if (null? x)
       (set-cdr! obj (cons 
			     (list '@ (list attr-name attr-value)) 
			     (sxml:content obj)))
       (cond 
	 ((assv attr-name x) => (lambda (y)
				  (set-car! (cdr y) attr-value)))
	 (else (set-car! (cdr obj) 
			 (append (list '@ (list attr-name attr-value)) 
				x)))))
     obj)
   (sxml:attr-list obj)))


sxml:append-content!
Index
Appends <new-data> to the content of the <obj>
The resulting SXML element is normalized
(define (sxml:append-content! obj . new-data)
  (sxml:content! obj
		     (append (sxml:content obj) 
			     new-data))
  obj)


sxml:insert-unique!
Index
This function inserts new sub-elements in sxml node <obj>
if there is no elements with the same name yet
<element> is a sxml element to insert

Absolete name: if-insert-node!
(define (sxml:insert-unique! obj element)
  (cond
    ((null? ((sxpath `(,(sxml:name element))) obj))
	    (sxml:append-content! obj element))
    (else #f)))

sxml:normalize!
Index
Normalize SXML data structure for the given <obj> and its descendants
Returns: normalized SXML element
(define (sxml:normalize! obj)
  (if (not (sxml:shallow-normalized? obj))
    ((lambda(x) 
       (if (null? x)
          (set-cdr! obj (cons '(@) (sxml:content obj)))
	  (set-cdr! obj (cons (cons '@ x) (sxml:content obj)))
	  ))
     (sxml:attr-list obj)))
  (for-each
    sxml:normalize!
    (sxml:child-elements obj))
   obj)

sxml:squeeze!
Index
Eliminates empty lists of attributes for the given SXML element 
<obj> and its descendants ("minimize" it)
Returns: minimized SXML element
(define (sxml:squeeze! obj)
  (if (null? (sxml:attr-list obj))
    (set-cdr! obj (sxml:content obj)))
    (for-each 
      sxml:squeeze!
	(sxml:child-elements obj))
    obj)


node-typeof-list?
Index
The function node-typeof-list? takes a type criterion and returns
a function, which, when applied to a node, will tell if the node satisfies
the test.
	node-typeof? :: Crit -> Node -> Boolean

The criterion 'crit' is 
one of the following symbols:
	id		- tests if the Node has the right name (id)
	@		- tests if the Node is an <attributes-coll>
	*		- tests if the Node is an <Element>
	*text*		- tests if the Node is a text node
	*data*		- tests if the Node is a data node 
(text, number, boolean, etc)
	*PI*		- tests if the Node is a PI node
	*any*		- #t for any type of Node
or list of symbols
	(id ...)	- tests if the Node has the right name, 
listed in (id ...) list
(define (node-typeof-list? crit)
    (define (present? x)
      ((if (list? crit)
	 memq 
	 eq)
       x crit))
  (lambda (node)
    (cond 
      ((pair? node)
       (or
	 (present? '*any*)
	 (present? (car node))
	 (and (present? '*)
	      (not (memq (car node) 
			 '(@ *PI* *COMMENT* *ENTITY* *NAMESPACES*))))
	 (and (present? '*data*) (not (list? node)))
	 ))
      ((string? node) 
       (or 
	 (present? '*any*)
	 (present? '*text*)
	 (present? '*data*)))
      (else
	(or
	  (present? '*any*)
	  (and (present? '*data*) (not (list? node))))))
    ))	
	   
	      

map-on-type
Index
Map children elements of the given nodeset using corresponding
handlers for subnodes in accordance to their types.
Each handler is a pair whose car is a tag name and cdr is a function 
of one argument to apply.
If an element has a type which is supported by one of handlers then
it is mapped using the function of this handler. 
If where is no handler for some element then it is omitted from the result.

Sample call
((map-on-type `(tag . ,tag-handler)
	 `(tag1 . ,tag1-handler)) c)
(define (map-on-type . handlers)
  (lambda(node)
    (map
      (lambda(x)
	((cdr (assq (sxml:name x) handlers)) x))
      ((select-kids
	 (node-typeof-list? (map car handlers))) node))   
    ))

if-sxpath
Index
sxpath always returns a list, which is #t in Scheme 
if-sxpath returns #f instead of empty list
(define (if-sxpath path)
  (lambda (obj)
   (let ((x ((sxpath path) obj)))
     (if (null? x) #f x))))

if-car-sxpath
Index
Returns first node found, if any.
Otherwise returns #f.
(define (if-car-sxpath path)
  (lambda (obj)
   (let ((x ((sxpath path) obj)))
     (if (null? x) #f (car x)))))

car-sxpath
Index
Returns first node found, if any.
Otherwise returns empty list.
(define (car-sxpath path)
  (lambda (obj)
   (let ((x ((sxpath path) obj)))
     (if (null? x) '() (car x)))))