S X M L T o o l s Swiss Army Knife for SXML data
Predicate which returns #t if <obj> is SXML node, otherwise returns #f.
Predicate which returns #t if <obj> is SXML element, otherwise returns #f.
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.
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.
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.
Returns a name of the given element Sample call: (sxml:name element) It is introduced for the sake of encapsulation.
Safe version of sxml:name, which returns #f if the given <obj> is not a SXML element. Otherwise returns its name.
Safe version of sxml:name, which returns #f if the given <obj> is not a SXML node. Otherwise returns its name.
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.
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
Returns a list of all the children elements for the given <obj>, <obj> which have to be minimized or normalized SXML element
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.
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)
Constructors and mutators
if the <new-content> is an empty list then the <obj> is transformed to an empty element The resulting SXML element is normalized
Ground function for attribute manipulations The resulting SXML element is normalized, if <new-attrlist> is empty, the cadr of <obj> is (@)
Change name of a SXML element
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
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
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
Appends <new-data> to the content of the <obj> The resulting SXML element is normalized
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!
Normalize SXML data structure for the given <obj> and its descendants Returns: normalized SXML element
Eliminates empty lists of attributes for the given SXML element <obj> and its descendants ("minimize" it) Returns: minimized SXML element
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 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)
sxpath always returns a list, which is #t in Scheme if-sxpath returns #f instead of empty list
Returns first node found, if any. Otherwise returns #f.
Returns first node found, if any. Otherwise returns empty list.
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 ))
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*)))))
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))))
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))))))
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)) '@)))
Returns a name of the given element Sample call: (sxml:name element) It is introduced for the sake of encapsulation.
(define sxml:name car)
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))
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))
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))
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)))))
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)))))
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)))) ))
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)))
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)
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)
Change name of a SXML element
(define (sxml:name! obj new-name) (set-car! obj new-name) obj)
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))))
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)))))
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)))
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)
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)))
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)
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)
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 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)) ))
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))))
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)))))
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)))))