#lang racket/base
(require "ssax/ssax.rkt"
"xpath-context_xlink.rkt")
(provide (all-defined-out))
(define (ddo:list-last lst)
(if (null? (cdr lst))
(car lst)
(ddo:list-last (cdr lst))))
(define (ddo:attr-child node)
(cond
((or (not (pair? node)) (null? (cdr node)) (memq (car node) '(*PI* *COMMENT* *ENTITY*)) ) '())
((and (pair? (cadr node))
(eq? '@ (caadr node)))
(append (cdadr node) (filter sxml:node? (cddr node))))
(else (filter sxml:node? (cdr node)))))
(define (ddo:attrs-and-values node)
(apply append
(map (lambda (a) (cons a (cdr a)))
(sxml:attr-list node))))
(define (ddo:discard-attributes node nodeset)
(let loop ((attrs (ddo:attrs-and-values (sxml:context->node node)))
(nset nodeset))
(if (or (null? attrs) (null? nset))
nset
(loop (cdr attrs)
(if (eq? (car attrs) (sxml:context->node (car nset)))
(cdr nset) nset)))))
(define (ddo:ancestor test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (let loop ((src (as-nodeset node))
(prev-ancestors '())
(res '()))
(if
(null? src) (reverse res)
(let ((curr (car src)))
(if
(sxml:context? curr)
(let rpt ((curr-ancs (reverse
(sxml:context->ancestors-u curr)))
(dupl '()))
(cond
((null? curr-ancs) (loop (cdr src) prev-ancestors res))
((memq (car curr-ancs) prev-ancestors)
(rpt (cdr curr-ancs)
(cons (car curr-ancs) dupl)))
(else (let creat ((new-ancestors dupl)
(curr-ancs curr-ancs)
(res res))
(cond
((null? curr-ancs) (loop (cdr src)
new-ancestors
res))
((test-pred? (car curr-ancs))
(creat (cons (car curr-ancs) new-ancestors)
(cdr curr-ancs)
(cons
(draft:smart-make-context
(car curr-ancs)
new-ancestors
num-anc)
res)))
(else (creat (cons (car curr-ancs) new-ancestors)
(cdr curr-ancs)
res)))))))
(loop (cdr src) prev-ancestors res))))))))
(define (ddo:ancestor-or-self test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (let loop ((src (as-nodeset node))
(prev-ancestors '())
(res '()))
(if
(null? src) (reverse res)
(let rpt ((curr-ancs (reverse
(sxml:context->content (car src))))
(dupl '()))
(cond
((null? curr-ancs) (loop (cdr src) prev-ancestors res))
((memq (car curr-ancs) prev-ancestors)
(rpt (cdr curr-ancs)
(cons (car curr-ancs) dupl)))
(else (let creat ((new-ancestors dupl)
(curr-ancs curr-ancs)
(res res))
(cond
((null? curr-ancs) (loop (cdr src)
new-ancestors
res))
((test-pred? (car curr-ancs))
(creat (cons (car curr-ancs) new-ancestors)
(cdr curr-ancs)
(cons
(draft:smart-make-context
(car curr-ancs)
new-ancestors
num-anc)
res)))
(else (creat (cons (car curr-ancs) new-ancestors)
(cdr curr-ancs)
res))))))))))))
(define ddo:attribute draft:attribute)
(define (ddo:child test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?)))
(letrec
((child4this
(lambda (curr-node src)
(let iter-attrs ((src src)
(res '()))
(cond
((null? src) (values
(append res
((draft:child test-pred? num-anc) curr-node))
src ))
((memq (sxml:context->node (car src))
(sxml:attr-list (sxml:context->node curr-node)))
(iter-attrs
(cdr src)
(append res ((draft:child test-pred? num-anc) (car src)))))
(else (let ((res-ancestors
(sxml:context->content curr-node)))
(let iter-cands ((res-candidates
(child (sxml:context->node curr-node)))
(src src)
(res res))
(cond
((null? src) (values
(append
res
(draft:siblings->context-set
((sxml:filter test-pred?) res-candidates)
(draft:list-head res-ancestors num-anc)))
src ))
((null? res-candidates)
(values res src))
(else (let rpt ((more (list (car res-candidates)))
(next (sxml:context->node (car src)))
(src src)
(res
(if
(test-pred? (car res-candidates))
(append
res
(list
(draft:smart-make-context
(car res-candidates)
res-ancestors num-anc)))
res)))
(cond
((null? more)
(iter-cands (cdr res-candidates) src res))
((eq? (car more) next)
(call-with-values
(lambda () (child4this (car src) (cdr src)))
(lambda (add-res new-src)
(if
(null? new-src)
(iter-cands (cdr res-candidates)
new-src
(append res add-res))
(rpt
(cdr more) (sxml:context->node (car new-src))
new-src
(append res add-res))))))
(else
(rpt
(append (ddo:attr-child (car more))
(cdr more))
next src res))))))))))))))
(lambda (node) (if
(nodeset? node)
(let iter ((nset node)
(res '()))
(if
(null? nset)
res
(call-with-values
(lambda () (child4this (car nset) (cdr nset)))
(lambda (add-res new-nset)
(iter new-nset (append res add-res))))))
((draft:child test-pred? num-anc) node))))))
(define (ddo:descendant test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?))
(desc (draft:descendant test-pred? num-anc)))
(lambda (node) (let loop ((src (as-nodeset node))
(next-node #f)
(content-to-scan '())
(res '()))
(if
(null? content-to-scan)
(cond
((null? src) (reverse res))
((null? (cdr src)) (append (reverse res)
(desc (car src))))
(else
(loop (cdr src)
(sxml:context->node (cadr src))
(let ((cntnt (sxml:context->content (car src))))
(map
(lambda (c) (cons c cntnt))
(child (sxml:context->node (car src)))))
res)))
(let ((curr-cntnt (car content-to-scan)))
(call-with-values
(lambda ()
(if
(eq? (car curr-cntnt) next-node)
(values
(cdr src)
(if (null? (cdr src)) #f
(sxml:context->node (cadr src))))
(values src next-node)))
(lambda (new-src new-next)
(loop new-src
new-next
(append
(map
(lambda (c) (cons c curr-cntnt))
(child (car curr-cntnt)))
(cdr content-to-scan))
(if
(test-pred? (car curr-cntnt)) (cons
(draft:smart-make-context
(car curr-cntnt) (cdr curr-cntnt) num-anc)
res)
res))))))))))
(define (ddo:descendant-or-self test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?))
(desc-os (draft:descendant-or-self test-pred? num-anc)))
(lambda (node) (let loop ((src (as-nodeset node))
(next-node #f)
(content-to-scan '())
(res '()))
(if
(null? content-to-scan)
(cond
((null? src) (reverse res))
((null? (cdr src)) (append (reverse res)
(desc-os (car src))))
(else
(loop (cdr src)
(sxml:context->node (cadr src))
(list (sxml:context->content (car src)))
res)))
(let ((curr-cntnt (car content-to-scan)))
(call-with-values
(lambda ()
(if
(eq? (car curr-cntnt) next-node)
(values
(cdr src)
(if (null? (cdr src)) #f
(sxml:context->node (cadr src))))
(values src next-node)))
(lambda (new-src new-next)
(loop new-src
new-next
(append
(map
(lambda (c) (cons c curr-cntnt))
(child (car curr-cntnt)))
(cdr content-to-scan))
(if
(test-pred? (car curr-cntnt)) (cons
(draft:smart-make-context
(car curr-cntnt) (cdr curr-cntnt) num-anc)
res)
res))))))))))
(define (ddo:following test-pred? . num-ancestors)
(let ((child (sxml:child sxml:node?))
(foll (apply draft:following (cons test-pred? num-ancestors))))
(lambda (node) (cond
((null? node) '())
((and (pair? node) (not (symbol? (car node)))) (if
(null? (cdr node)) (foll (car node))
(let loop ((candidate (car node))
(next (sxml:context->node (cadr node)))
(more (cdr node))
(descendants (list (sxml:context->node (car node)))))
(cond
((null? descendants)
(foll candidate))
((eq? (car descendants) next)
(if (null? (cdr more)) (foll (car more))
(loop (car more)
(sxml:context->node (cadr more))
(cdr more)
(list next))))
((memq next (ddo:attrs-and-values (car descendants)))
(foll (car more)))
(else (loop candidate next more
(append (child (car descendants)) (cdr descendants))))))))
(else (foll node))))))
(define (ddo:following-sibling test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?))
(all-following-siblings
(lambda (node) (if
(and (sxml:context? node)
(not (null? (sxml:context->ancestors-u node))))
(cond
((memq (sxml:context->node-u node)
(cdr (car (sxml:context->ancestors-u node))))
=> (lambda (x) x))
(else '()))
'() ))))
(letrec
((reordering
(lambda (res-candidates res-ancestors src)
(let loop ((res-candidates res-candidates)
(src src)
(res '())
(nonself? #f))
(cond
((null? res-candidates)
(values res src))
((null? src) (values
(append
res
(draft:siblings->context-set
((sxml:filter test-pred?)
(if nonself?
res-candidates
(cdr res-candidates)))
(draft:list-head res-ancestors num-anc)))
src ))
((eq? (car res-candidates) (sxml:context->node (car src)))
(loop res-candidates (cdr src) res nonself?))
(else (let ((res-candidate (car res-candidates)))
(let rpt ((more (list res-candidate))
(next (sxml:context->node (car src)))
(src src)
(res (if
(and nonself? (test-pred? res-candidate))
(append
res
(list
(draft:smart-make-context
res-candidate res-ancestors num-anc)))
res)))
(cond
((null? more)
(loop (cdr res-candidates) src res #t))
((eq? (car more) next)
(call-with-values
(lambda ()
(reordering
(all-following-siblings (car src))
(sxml:context->ancestors (car src))
(cdr src)))
(lambda (add-res new-src)
(if
(null? new-src)
(loop (cdr res-candidates)
new-src
(append res add-res)
#t)
(rpt (cdr more) (sxml:context->node (car new-src))
new-src
(append res add-res))))))
((memq next (ddo:attrs-and-values (car more)))
(if
(null? (cdr src))
(loop (cdr res-candidates)
(cdr src) res
#t)
(rpt more (sxml:context->node (car src))
(cdr src)
res)))
(else
(rpt (append (child (car more)) (cdr more))
next src res)))))))))))
(lambda (node) (if
(nodeset? node)
(let iter ((nset node)
(res '()))
(if
(null? nset)
res
(call-with-values
(lambda ()
(reordering (all-following-siblings (car nset))
(sxml:context->ancestors (car nset))
(cdr nset)))
(lambda (add-res new-nset)
(iter new-nset (append res add-res))))))
((draft:following-sibling test-pred? num-anc) node))))))
(define ddo:namespace draft:namespace)
(define (ddo:parent test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (let loop ((src (as-nodeset node))
(prev-parents '())
(res '()))
(if
(null? src)
(reverse res)
(let ((curr (car src)))
(if
(and (sxml:context? curr)
(not (null? (sxml:context->ancestors-u curr))))
(let ((curr-parent (car (sxml:context->ancestors-u curr))))
(if
(memq curr-parent prev-parents) (loop (cdr src) prev-parents res)
(loop (cdr src)
(cons curr-parent prev-parents)
(if
(test-pred? curr-parent)
(cons
(draft:smart-make-context
curr-parent
(cdr (sxml:context->ancestors-u curr))
num-anc)
res)
res))))
(loop (cdr src) prev-parents res))))))))
(define (ddo:preceding test-pred? . num-ancestors)
(let ((prec (apply draft:preceding (cons test-pred? num-ancestors))))
(lambda (node) (cond
((null? node) '())
((and (pair? node) (not (symbol? (car node)))) (if
(null? (cdr node)) (prec (car node))
(let ((node (reverse node)))
(let loop ((candidate (car node))
(next (sxml:context->node (cadr node)))
(more (cdr node))
(descendants
(reverse
(ddo:attr-child (sxml:context->node (car node))))))
(cond
((null? descendants)
(reverse (prec candidate)))
((eq? (car descendants) next)
(if (null? (cdr more)) (reverse (prec (car more)))
(loop (car more)
(sxml:context->node (cadr more))
(cdr more)
(reverse (ddo:attr-child next)))))
(else (loop candidate next more
(append (reverse (ddo:attr-child (car descendants)))
(cdr descendants)))))))))
(else (reverse (prec node)))))))
(define (ddo:preceding-sibling test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?))
(all-preceding-siblings
(lambda (node) (if
(and (sxml:context? node)
(not (null? (sxml:context->ancestors-u node))))
(cond
((memq (sxml:context->node-u node)
(reverse
(cdr (car (sxml:context->ancestors-u node)))))
=> cdr)
(else '()))
'() ))))
(letrec
((reordering
(lambda (res-candidates res-ancestors src)
(let loop ((res-candidates res-candidates)
(src src)
(res '()))
(cond
((null? res-candidates)
(values res src))
((null? src) (values
(append
res
(draft:siblings->context-set
((sxml:filter test-pred?) res-candidates)
(draft:list-head res-ancestors num-anc)))
src ))
((eq? (car res-candidates) (sxml:context->node (car src)))
(loop res-candidates (cdr src) res))
(else (let ((res-candidate (car res-candidates)))
(let rpt ((more (reverse (child res-candidate)))
(next (sxml:context->node (car src)))
(src src)
(res res))
(cond
((null? more)
(loop
(cdr res-candidates)
src
(if (test-pred? res-candidate)
(append res
(list
(draft:smart-make-context
res-candidate res-ancestors num-anc)))
res)))
((eq? (car more) next)
(call-with-values
(lambda ()
(reordering
(all-preceding-siblings (car src))
(sxml:context->ancestors (car src))
(cdr src)))
(lambda (add-res new-src)
(let ((new-src
(cond
((null? new-src) new-src)
((eq? res-candidate
(sxml:context->node (car new-src)))
(cdr new-src))
(else new-src))))
(if
(null? new-src)
(loop (cdr res-candidates)
new-src
(if
(test-pred? res-candidate)
(append
res
add-res
(list
(draft:smart-make-context
res-candidate res-ancestors num-anc)))
(append res add-res)))
(rpt (cdr more) (sxml:context->node (car new-src))
new-src
(append res add-res)))))))
(else
(rpt (append (reverse (child (car more))) (cdr more))
next src res)))))))))))
(lambda (node) (if
(nodeset? node)
(let iter ((nset (reverse node))
(res '()))
(if
(null? nset)
(reverse res)
(call-with-values
(lambda ()
(reordering (all-preceding-siblings (car nset))
(sxml:context->ancestors (car nset))
(cdr nset)))
(lambda (add-res new-nset)
(iter new-nset (append res add-res))))))
((draft:following-sibling test-pred? num-anc) node))))))
(define ddo:self draft:self)
(define (ddo:following-single-level test-pred? . num-ancestors)
(let ((foll (apply draft:following
(cons test-pred? num-ancestors))))
(lambda (node) (cond
((null? node) '())
((and (pair? node) (not (symbol? (car node)))) (foll (car node)))
(else (foll node))))))
(define (ddo:following-sibling-single-level test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (let loop ((src (as-nodeset node))
(res '()))
(if
(null? src) (reverse res)
(let ((curr (car src)))
(if
(and (sxml:context? curr)
(not (null? (sxml:context->ancestors-u curr))))
(cond
((memq (sxml:context->node-u curr)
(cdr (car (sxml:context->ancestors-u curr))))
=> (lambda (foll-siblings)
(let rpt ((foll-siblings (cdr foll-siblings))
(src (cdr src))
(res res))
(cond
((null? foll-siblings)
(loop src res))
((null? src) (append
(reverse res)
(draft:siblings->context-set
((sxml:filter test-pred?) foll-siblings)
(draft:list-head
(sxml:context->ancestors-u curr) num-anc))))
(else
(rpt
(cdr foll-siblings)
(if (eq? (car foll-siblings)
(sxml:context->node (car src)))
(cdr src) src)
(if (test-pred? (car foll-siblings))
(cons
(draft:smart-make-context
(car foll-siblings)
(sxml:context->ancestors-u curr)
num-anc)
res)
res)))))))
(else (loop (cdr src) res)))
(loop (cdr src) res) )))))))
(define (ddo:parent-single-level test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (let loop ((src (as-nodeset node))
(prev-parent #f)
(res '()))
(if
(null? src)
(reverse res)
(let ((curr (car src)))
(if
(and (sxml:context? curr)
(not (null? (sxml:context->ancestors-u curr))))
(let ((curr-parent (car (sxml:context->ancestors-u curr))))
(if
(eq? curr-parent prev-parent) (loop (cdr src) prev-parent res)
(loop (cdr src) curr-parent
(if
(test-pred? curr-parent)
(cons
(draft:smart-make-context
curr-parent
(cdr (sxml:context->ancestors-u curr))
num-anc)
res)
res))))
(loop (cdr src) prev-parent res))))))))
(define (ddo:preceding-single-level test-pred? . num-ancestors)
(let ((prec (apply draft:preceding
(cons test-pred? num-ancestors))))
(lambda (node) (cond
((null? node) '())
((and (pair? node) (not (symbol? (car node)))) (reverse (prec (ddo:list-last node))))
(else (reverse (prec node)))))))
(define (ddo:preceding-sibling-single-level test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (let loop ((src (reverse (as-nodeset node)))
(res '()))
(if
(null? src) res
(let ((curr (car src)))
(if
(and (sxml:context? curr)
(not (null? (sxml:context->ancestors-u curr))))
(cond
((memq (sxml:context->node-u curr)
(reverse
(cdr (car (sxml:context->ancestors-u curr)))))
=> (lambda (prec-siblings)
(let rpt ((prec-siblings (cdr prec-siblings))
(src (cdr src))
(res res))
(cond
((null? prec-siblings)
(loop src res))
((null? src) (append
(reverse
(draft:siblings->context-set
((sxml:filter test-pred?) prec-siblings)
(draft:list-head
(sxml:context->ancestors-u curr) num-anc)))
res))
(else
(rpt
(cdr prec-siblings)
(if (eq? (car prec-siblings)
(sxml:context->node (car src)))
(cdr src) src)
(if (test-pred? (car prec-siblings))
(cons
(draft:smart-make-context
(car prec-siblings)
(sxml:context->ancestors-u curr)
num-anc)
res)
res)))))))
(else (loop (cdr src) res)))
(loop (cdr src) res) )))))))
(define (ddo:ancestor-pos test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(letrec
( (assmemq
(lambda (key lst)
(cond
((null? lst) #f)
((eq? key (caar lst)) lst)
(else (assmemq key (cdr lst)))))))
(lambda (node) (let loop ((src (as-nodeset node))
(prev-ancestors '())
(ancs-alist '())
(pos-res '())
(vacant-num 1))
(if
(null? src) pos-res
(let ((curr (car src)))
(cond
((or (not (sxml:context? curr))
(null? (sxml:context->ancestors-u curr)))
(loop (cdr src) prev-ancestors ancs-alist pos-res vacant-num))
((and (not (null? prev-ancestors))
(eq? (car (sxml:context->ancestors-u curr))
(car prev-ancestors)))
(loop (cdr src) prev-ancestors ancs-alist pos-res vacant-num))
(else
(let rpt ((curr-ancs (sxml:context->ancestors-u curr))
(new-content '()))
(cond
((or (null? curr-ancs) (memq (car curr-ancs) prev-ancestors))
=> (lambda (prev-tail)
(call-with-values
(lambda()
(if
(pair? prev-tail)
(let ((t
(assmemq (car prev-tail) ancs-alist)))
(values prev-tail t (cdar t)))
(values '() '() '())))
(lambda (prev-ancestors ancs-alist this-nset)
(let creat ((prev-ancestors prev-ancestors)
(ancs-alist ancs-alist)
(vacant-num vacant-num)
(this-nset this-nset)
(new-content new-content))
(if
(null? new-content) (loop (cdr src)
prev-ancestors
ancs-alist
(cons this-nset pos-res)
vacant-num)
(let ((new-this-nset
(if
(test-pred? (caar new-content))
(cons
(cons
(draft:smart-make-context
(caar new-content)
(cdar new-content)
num-anc)
vacant-num)
this-nset)
this-nset)))
(creat (car new-content)
(cons
(cons
(caar new-content)
new-this-nset)
ancs-alist)
(+ vacant-num 1)
new-this-nset
(cdr new-content)))))))))
(else
(rpt (cdr curr-ancs)
(cons curr-ancs new-content))))))))))))))
(define (ddo:ancestor-or-self-pos test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(letrec
( (assmemq
(lambda (key lst)
(cond
((null? lst) #f)
((eq? key (caar lst)) lst)
(else (assmemq key (cdr lst)))))))
(lambda (node) (let loop ((src (as-nodeset node))
(prev-ancestors '())
(ancs-alist '())
(pos-res '())
(vacant-num 1))
(if
(null? src) pos-res
(let rpt ((curr-ancs (sxml:context->content (car src)))
(new-content '()))
(cond
((or (null? curr-ancs) (memq (car curr-ancs) prev-ancestors))
=> (lambda (prev-tail)
(call-with-values
(lambda ()
(if
(pair? prev-tail)
(let ((t (assmemq (car prev-tail) ancs-alist)))
(values prev-tail t (cdar t)))
(values '() '() '())))
(lambda (prev-ancestors ancs-alist this-nset)
(let creat ((prev-ancestors prev-ancestors)
(ancs-alist ancs-alist)
(vacant-num vacant-num)
(this-nset this-nset)
(new-content new-content))
(if
(null? new-content) (loop (cdr src)
prev-ancestors
ancs-alist
(cons this-nset pos-res)
vacant-num)
(let ((new-this-nset
(if
(test-pred? (caar new-content))
(cons
(cons
(draft:smart-make-context
(caar new-content)
(cdar new-content)
num-anc)
vacant-num)
this-nset)
this-nset)))
(creat (car new-content)
(cons
(cons
(caar new-content)
new-this-nset)
ancs-alist)
(+ vacant-num 1)
new-this-nset
(cdr new-content)))))))))
(else
(rpt (cdr curr-ancs)
(cons curr-ancs new-content)))))))))))
(define (ddo:child-pos test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?)))
(letrec
( (create-pos-nset
(lambda (nset ancestors vacant-num)
(if (null? nset)
'()
(cons
(cons (if (null? ancestors)
(car nset)
(draft:make-context (car nset) ancestors))
vacant-num)
(create-pos-nset (cdr nset) ancestors (+ vacant-num 1))))))
(src-walk
(lambda (curr-node src order-num)
(let ((curr-children
(child (sxml:context->node curr-node))))
(if
(null? curr-children) (values '() src order-num)
(let ((curr-ancestors (draft:list-head
(sxml:context->content curr-node)
num-anc)))
(if
(null? src) (values (list (create-pos-nset
((sxml:filter test-pred?) curr-children)
curr-ancestors order-num))
src #f )
(let loop ((src src)
(next-node (sxml:context->node (car src)))
(curr-children (cdr curr-children))
(desc-to-scan (list (car curr-children)))
(this-res
(if
(test-pred? (car curr-children))
(list
(cons
(if (null? curr-ancestors)
(car curr-children)
(draft:make-context
(car curr-children) curr-ancestors))
order-num))
'()))
(pos-result '())
(order-num (+ order-num 1)))
(cond
((null? desc-to-scan)
(if
(null? curr-children)
(values (cons (reverse this-res) pos-result)
src
order-num)
(loop src next-node
(cdr curr-children)
(list (car curr-children))
(if
(test-pred? (car curr-children))
(cons
(cons
(if (null? curr-ancestors)
(car curr-children)
(draft:make-context
(car curr-children) curr-ancestors))
order-num)
this-res)
this-res)
pos-result
(+ order-num 1))))
((eq? (car desc-to-scan) next-node)
(call-with-values
(lambda ()
(src-walk (car src)
(cdr src)
order-num))
(lambda (new-pos-res new-src new-order-num)
(if
(null? new-src) (values
(cons
(append
(reverse this-res)
(create-pos-nset
((sxml:filter test-pred?) curr-children)
curr-ancestors order-num))
(append pos-result new-pos-res))
new-src #f )
(loop new-src
(sxml:context->node (car new-src))
curr-children
(cdr desc-to-scan) this-res
(append pos-result new-pos-res)
new-order-num)))))
(else (loop src next-node curr-children
(append (ddo:attr-child (car desc-to-scan))
(cdr desc-to-scan))
this-res
pos-result
order-num)))))))))))
(lambda (node) (let rpt ((src (as-nodeset node))
(pos-result '())
(order-num 1))
(if
(null? src) (filter (lambda (x) (not (null? x)))
pos-result)
(call-with-values
(lambda () (src-walk (car src) (cdr src) order-num))
(lambda (new-pos-res new-src new-order-num)
(rpt new-src
(append pos-result new-pos-res)
new-order-num)))))))))
(define (ddo:descendant-pos test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?))
(desc (draft:descendant test-pred? num-anc)))
(letrec
((src-walk
(lambda (curr-node src order-num)
(let loop ((src src)
(next-node (if (null? src)
#f
(sxml:context->node (car src))))
(content-to-scan
(let ((cntnt (sxml:context->content curr-node)))
(map
(lambda (c) (cons c cntnt))
(child (sxml:context->node curr-node)))))
(this-res '())
(pos-result '())
(order-num order-num))
(if
(null? content-to-scan)
(values (cons (reverse this-res) pos-result)
src
(+ order-num 1))
(let ((curr-cntnt (car content-to-scan)))
(if
(eq? (car curr-cntnt) next-node)
(call-with-values
(lambda () (src-walk (car src)
(cdr src)
(+ order-num 1)))
(lambda (new-pos-res new-src new-order-num)
(loop new-src
(if (null? new-src)
#f
(sxml:context->node (car new-src)))
(cdr content-to-scan) (append
(reverse (car new-pos-res))
(if (test-pred? (car curr-cntnt))
(cons
(cons
(draft:smart-make-context
(car curr-cntnt) (cdr curr-cntnt) num-anc)
order-num)
this-res)
this-res))
(append pos-result new-pos-res)
new-order-num)))
(loop src
next-node
(append (map
(lambda (c) (cons c curr-cntnt))
(child (car curr-cntnt)))
(cdr content-to-scan))
(if (test-pred? (car curr-cntnt)) (cons
(cons
(draft:smart-make-context
(car curr-cntnt) (cdr curr-cntnt) num-anc)
order-num)
this-res)
this-res)
pos-result
(+ order-num 1)))))))))
(lambda (node) (let rpt ((src (as-nodeset node))
(pos-result '())
(order-num 1))
(if
(null? src) (filter (lambda (x) (not (null? x)))
pos-result)
(call-with-values
(lambda () (src-walk (car src) (cdr src) order-num))
(lambda (new-pos-res new-src new-order-num)
(rpt new-src
(append pos-result new-pos-res)
new-order-num)))))))))
(define (ddo:descendant-or-self-pos test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?)))
(letrec
((src-walk
(lambda (curr-node src order-num)
(let loop ((src src)
(next-node (if (null? src)
#f
(sxml:context->node (car src))))
(content-to-scan
(list (sxml:context->content curr-node)))
(this-res '())
(pos-result '())
(order-num order-num))
(if
(null? content-to-scan)
(values (cons (reverse this-res) pos-result)
src
(+ order-num 1))
(let ((curr-cntnt (car content-to-scan)))
(if
(eq? (car curr-cntnt) next-node)
(call-with-values
(lambda () (src-walk (car src) (cdr src) order-num))
(lambda (new-pos-res new-src new-order-num)
(loop new-src
(if (null? new-src)
#f
(sxml:context->node (car new-src)))
(cdr content-to-scan) (append
(reverse (car new-pos-res))
this-res)
(append pos-result new-pos-res)
new-order-num)))
(loop src
next-node
(append (map
(lambda (c) (cons c curr-cntnt))
(child (car curr-cntnt)))
(cdr content-to-scan))
(if (test-pred? (car curr-cntnt)) (cons
(cons
(draft:smart-make-context
(car curr-cntnt) (cdr curr-cntnt) num-anc)
order-num)
this-res)
this-res)
pos-result
(+ order-num 1)))))))))
(lambda (node) (let rpt ((src (as-nodeset node))
(pos-result '())
(order-num 1))
(if
(null? src) (filter (lambda (x) (not (null? x)))
pos-result)
(call-with-values
(lambda () (src-walk (car src) (cdr src) order-num))
(lambda (new-pos-res new-src new-order-num)
(rpt new-src
(append pos-result new-pos-res)
new-order-num)))))))))
(define (ddo:following-sibling-pos test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?)))
(letrec
((associate-num
(lambda (nset ancestors vacant-num)
(if (null? nset)
nset
(cons
(cons
(if (null? ancestors)
(car nset)
(draft:make-context (car nset) ancestors))
vacant-num)
(associate-num (cdr nset) ancestors (+ vacant-num 1))))))
(process-single
(lambda (curr src vacant-num)
(if
(or (not (sxml:context? curr))
(null? (sxml:context->ancestors-u curr)))
(values '() src vacant-num)
(cond
((memq (sxml:context->node-u curr)
(cdr (car (sxml:context->ancestors-u curr))))
=>
(lambda (foll-siblings)
(let ((ancestors
(draft:list-head
(sxml:context->ancestors-u curr) num-anc)))
(let loop ((foll-siblings (cdr foll-siblings))
(descs (child (car foll-siblings)))
(src (ddo:discard-attributes
(car foll-siblings) src))
(vacant-num vacant-num)
(res '())
(pos-res '()))
(cond
((null? src)
(values
(cons
(append
(reverse res)
(associate-num
foll-siblings ancestors vacant-num))
pos-res)
src #f ))
((null? descs) (if
(null? foll-siblings) (values (cons (reverse res) pos-res)
src
vacant-num)
(let ((new-res
(if (test-pred? (car foll-siblings))
(cons
(cons
(if (null? ancestors)
(car foll-siblings)
(draft:make-context
(car foll-siblings) ancestors))
vacant-num)
res)
res)))
(if
(eq? (car foll-siblings)
(sxml:context->node (car src)))
(call-with-values
(lambda ()
(process-single
(car src) (cdr src) (+ vacant-num 1)))
(lambda (new-pos-res new-src new-vacant)
(values (cons
(append
(reverse new-res)
(if (null? new-pos-res)
'() (car new-pos-res)))
(append pos-res new-pos-res))
new-src
new-vacant)))
(loop (cdr foll-siblings)
(ddo:attr-child (car foll-siblings))
(ddo:discard-attributes
(car foll-siblings) src)
(+ vacant-num 1)
new-res
pos-res)))))
((eq? (car descs) (sxml:context->node (car src)))
(call-with-values
(lambda ()
(process-single
(car src) (cdr src) vacant-num))
(lambda (new-pos-res new-src new-vacant)
(loop foll-siblings
(cdr descs) new-src
new-vacant
res
(cons pos-res new-pos-res)))))
(else
(loop foll-siblings
(append (child (car descs)) (cdr descs))
(ddo:discard-attributes (car descs) src)
vacant-num
res
pos-res)))))))
(else
(values '() src vacant-num)))))))
(lambda (node) (when (nodeset? node)
(let iter ((src node)
(pos-res '())
(vacant-num 1))
(if
(null? src)
(filter (lambda (x) (not (null? x)))
pos-res)
(call-with-values
(lambda () (process-single (car src) (cdr src) vacant-num))
(lambda (new-pos-res new-src new-vacant)
(iter new-src
(append pos-res new-pos-res)
new-vacant))))))))))
(define (ddo:parent-pos test-pred? . num-ancestors)
(let ((parent (apply ddo:parent (cons test-pred? num-ancestors))))
(letrec
((add-order-num
(lambda (num nset)
(if (null? nset)
nset
(cons (list (cons (car nset) num))
(add-order-num (+ num 1) (cdr nset)))))))
(lambda (node) (add-order-num 1 (parent node))))))
(define (ddo:preceding-sibling-pos test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (sxml:child sxml:node?))
(reverse-desc (lambda (node)
(let scan ((more (ddo:attr-child node))
(res '()))
(if (null? more) res
(scan (append (ddo:attr-child (car more))
(cdr more))
(cons (car more) res)))))))
(letrec
((associate-num
(lambda (nset ancestors vacant-num)
(if (null? nset)
nset
(cons
(cons
(if (null? ancestors)
(car nset)
(draft:make-context (car nset) ancestors))
vacant-num)
(associate-num (cdr nset) ancestors (- vacant-num 1))))))
(process-single
(lambda (curr src vacant-num)
(if
(or (not (sxml:context? curr))
(null? (sxml:context->ancestors-u curr)))
(values '() src vacant-num)
(cond
((memq (sxml:context->node-u curr)
(reverse
(cdr (car (sxml:context->ancestors-u curr)))))
=>
(lambda (prec-siblings) (if
(null? (cdr prec-siblings)) (values '() src vacant-num)
(let ((ancestors
(draft:list-head
(sxml:context->ancestors-u curr) num-anc)))
(let loop ((prec-siblings (cdr prec-siblings))
(descs (reverse-desc (cadr prec-siblings)))
(src src)
(vacant-num vacant-num)
(res '())
(pos-res '()))
(cond
((null? src)
(values
(cons
(append
(reverse res)
(associate-num
prec-siblings
ancestors vacant-num))
pos-res)
src #f ))
((null? descs) (let ((new-res
(if (test-pred? (car prec-siblings))
(cons
(cons
(if (null? ancestors)
(car prec-siblings)
(draft:make-context
(car prec-siblings) ancestors))
vacant-num)
res)
res)))
(cond
((eq? (car prec-siblings) (sxml:context->node (car src)))
(call-with-values
(lambda ()
(process-single
(car src) (cdr src) (- vacant-num 1)))
(lambda (new-pos-res new-src new-vacant)
(values (cons
(append
(reverse new-res)
(if (null? new-pos-res)
'() (car new-pos-res)))
(append pos-res new-pos-res))
new-src
new-vacant))))
((null? (cdr prec-siblings)) (values (cons (reverse new-res) pos-res)
src
vacant-num))
(else
(loop (cdr prec-siblings)
(reverse-desc (cadr prec-siblings))
src
(- vacant-num 1)
new-res
pos-res)))))
((eq? (car descs) (sxml:context->node (car src)))
(call-with-values
(lambda ()
(process-single
(car src) (cdr src) vacant-num))
(lambda (new-pos-res new-src new-vacant)
(loop prec-siblings
(cdr descs) new-src
new-vacant
res
(append pos-res new-pos-res)))))
(else
(loop prec-siblings
(cdr descs)
src
vacant-num
res
pos-res))))))))
(else
(values '() src vacant-num)))))))
(lambda (node) (when (nodeset? node)
(let iter ((src (reverse node))
(pos-res '())
(vacant-num -1))
(if
(null? src)
(filter (lambda (x) (not (null? x)))
pos-res)
(call-with-values
(lambda () (process-single (car src) (cdr src) vacant-num))
(lambda (new-pos-res new-src new-vacant)
(iter new-src
(append new-pos-res pos-res)
new-vacant))))))))))
(define (ddo:following-single-level-pos test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(descend (draft:descendant-or-self test-pred? num-anc))
(follow (draft:following test-pred? num-anc)))
(letrec
( (process-single
(lambda (curr src vacant-num)
(cond
((null? src) (let add-labels ((to-scan (follow curr))
(res '())
(vacant-num vacant-num))
(if (null? to-scan)
(list (reverse res))
(add-labels (cdr to-scan)
(cons (cons (car to-scan) vacant-num) res)
(+ vacant-num 1)))))
((not (sxml:context? curr)) (cons '() (process-single (car src) (cdr src) vacant-num)))
(else
(let ((next (sxml:context->node (car src))))
(let loop ((this-level (sxml:context->node-u curr))
(ancs-to-view (sxml:context->ancestors-u curr))
(content-set '())
(pos-nset '())
(vacant-num vacant-num))
(cond
((null? content-set) (cond
((null? ancs-to-view)
(cons
(reverse pos-nset)
(process-single (car src) (cdr src) vacant-num)))
((memq next (sxml:attr-list (car ancs-to-view)))
(let ((pos-result
(process-single (car src) (cdr src) vacant-num)))
(cons
(append (reverse pos-nset) (car pos-result))
pos-result)))
(else (loop
(car ancs-to-view)
(cdr ancs-to-view)
(map
(lambda (n) (cons n (cdr ancs-to-view)))
(cond
((memq this-level
(cdr (car ancs-to-view)))
=> cdr)
(else ((select-kids sxml:node?) (car ancs-to-view)))))
pos-nset
vacant-num))))
((memq next (sxml:attr-list (caar ancs-to-view)))
(let ((pos-result
(process-single (car src) (cdr src) vacant-num)))
(cons
(append (reverse pos-nset) (car pos-result))
pos-result)))
((eq? (caar content-set) next)
(let add-desc ((to-scan
(descend
(draft:smart-make-context
(caar content-set)
(cdar content-set)
num-anc)))
(pos-nset pos-nset)
(vacant-num vacant-num))
(if
(null? to-scan)
(let ((pos-result
(process-single
(car src) (cdr src) vacant-num)))
(cons
(append (reverse pos-nset) (car pos-result))
pos-result))
(add-desc (cdr to-scan)
(cons (cons (car to-scan) vacant-num)
pos-nset)
(+ vacant-num 1)))))
(else (loop
this-level
ancs-to-view
(append
(map
(lambda (n) (cons n (car content-set)))
((sxml:child sxml:node?) (caar content-set)))
(cdr content-set))
(if
(test-pred? (caar content-set))
(cons (cons (draft:smart-make-context
(caar content-set) (cdar content-set)
num-anc)
vacant-num)
pos-nset)
pos-nset)
(+ vacant-num 1)))))))))))
(lambda (node) (let ((nset (as-nodeset node)))
(if (null? nset) nset
(filter (lambda (x) (not (null? x)))
(process-single (car nset) (cdr nset) 1))))))))
(define (ddo:following-sibling-single-level-pos test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(letrec
( (process-single
(lambda (curr src vacant-num)
(if
(or (not (sxml:context? curr))
(null? (sxml:context->ancestors-u curr)))
(if (null? src) '()
(process-single (car src) (cdr src) vacant-num))
(cond
((memq (sxml:context->node-u curr)
(cdr (car (sxml:context->ancestors-u curr))))
=> (lambda (foll-siblings)
(let ((ancestors
(draft:list-head
(sxml:context->ancestors-u curr) num-anc)))
(if
(null? src) (let no-more ((foll-siblings (cdr foll-siblings))
(res '())
(vacant-num vacant-num))
(if
(null? foll-siblings) (list (reverse res))
(no-more
(cdr foll-siblings)
(if (test-pred? (car foll-siblings))
(cons
(cons
(if (null? ancestors)
(car foll-siblings)
(draft:make-context
(car foll-siblings) ancestors))
vacant-num)
res)
res)
(+ vacant-num 1))))
(let ((next (sxml:context->node (car src))))
(let more ((foll-siblings (cdr foll-siblings))
(res '())
(vacant-num vacant-num))
(if
(null? foll-siblings) (cons
(reverse res)
(process-single (car src) (cdr src) vacant-num))
(let ((new-res
(if (test-pred? (car foll-siblings))
(cons
(cons
(if (null? ancestors)
(car foll-siblings)
(draft:make-context
(car foll-siblings) ancestors))
vacant-num)
res)
res)))
(if
(eq? (car foll-siblings) next) (let ((pos-res
(process-single
(car src)
(cdr src)
(+ vacant-num 1))))
(if
(null? pos-res) (list (reverse new-res))
(cons (append
(reverse new-res) (car pos-res))
pos-res)))
(more (cdr foll-siblings)
new-res
(+ vacant-num 1)))))))))))
(else (if (null? src) '()
(process-single (car src) (cdr src) vacant-num))))))))
(lambda (node) (let ((nset (as-nodeset node)))
(if (null? nset) nset
(filter (lambda (x) (not (null? x)))
(process-single (car nset) (cdr nset) 1))))))))
(define (ddo:parent-single-level-pos test-pred? . num-ancestors)
(let ((parent
(apply ddo:parent-single-level (cons test-pred? num-ancestors))))
(letrec
((add-order-num
(lambda (num nset)
(if (null? nset)
nset
(cons (list (cons (car nset) num))
(add-order-num (+ num 1) (cdr nset)))))))
(lambda (node) (add-order-num 1 (parent node))))))
(define (ddo:preceding-single-level-pos test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(descend (draft:descendant-or-self test-pred? num-anc))
(precede (draft:preceding test-pred? num-anc)))
(letrec
( (process-single
(lambda (curr src vacant-num)
(cond
((null? src) (let add-labels ((to-scan (precede curr))
(res '())
(vacant-num vacant-num))
(if (null? to-scan)
(list (reverse res))
(add-labels (cdr to-scan)
(cons (cons (car to-scan) vacant-num) res)
(- vacant-num 1)))))
((not (sxml:context? curr)) (cons '() (process-single (car src) (cdr src) vacant-num)))
(else
(let ((next (sxml:context->node (car src))))
(let loop ((this-level (sxml:context->node-u curr))
(ancs-to-view (sxml:context->ancestors-u curr))
(content-set '())
(pos-nset '())
(vacant-num vacant-num))
(cond
((null? content-set) (if
(null? ancs-to-view)
(cons
(reverse pos-nset)
(process-single (car src) (cdr src) vacant-num))
(loop
(car ancs-to-view)
(cdr ancs-to-view)
(reverse
(map
sxml:context->content
(descend
(map
(lambda (n)
(draft:smart-make-context
n (cdr ancs-to-view) num-anc))
(cond
((memq this-level
(reverse
((select-kids sxml:node?)
(car ancs-to-view))))
=> (lambda (nset) (reverse (cdr nset))))
(else '()))))))
pos-nset
vacant-num)))
((eq? (caar content-set) next)
(let ((pos-result
(process-single
(car src)
(cdr src)
(- vacant-num 1))))
(cons
(append
(reverse
(if
(test-pred? (caar content-set))
(cons (cons (draft:smart-make-context
(caar content-set) (cdar content-set)
num-anc)
vacant-num)
pos-nset)
pos-nset))
(car pos-result))
pos-result)))
(else (loop
this-level
ancs-to-view
(cdr content-set)
(if
(test-pred? (caar content-set))
(cons (cons (draft:smart-make-context
(caar content-set) (cdar content-set)
num-anc)
vacant-num)
pos-nset)
pos-nset)
(- vacant-num 1)))))))))))
(lambda (node) (let ((nset (reverse (as-nodeset node))))
(if (null? nset) nset
(filter (lambda (x) (not (null? x)))
(process-single (car nset) (cdr nset) -1))))))))
(define (ddo:preceding-sibling-single-level-pos test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(letrec
( (process-single
(lambda (curr src vacant-num)
(if
(or (not (sxml:context? curr))
(null? (sxml:context->ancestors-u curr)))
(if (null? src) '()
(process-single (car src) (cdr src) vacant-num))
(cond
((memq (sxml:context->node-u curr)
(reverse
(cdr (car (sxml:context->ancestors-u curr)))))
=> (lambda (prec-siblings)
(let ((ancestors
(draft:list-head
(sxml:context->ancestors-u curr) num-anc)))
(if
(null? src) (let no-more ((prec-siblings (cdr prec-siblings))
(res '())
(vacant-num vacant-num))
(if
(null? prec-siblings) (list (reverse res))
(no-more
(cdr prec-siblings)
(if (test-pred? (car prec-siblings))
(cons
(cons
(if (null? ancestors)
(car prec-siblings)
(draft:make-context
(car prec-siblings) ancestors))
vacant-num)
res)
res)
(- vacant-num 1))))
(let ((next (sxml:context->node (car src))))
(let more ((prec-siblings (cdr prec-siblings))
(res '())
(vacant-num vacant-num))
(if
(null? prec-siblings) (cons
(reverse res)
(process-single (car src) (cdr src) vacant-num))
(let ((new-res
(if (test-pred? (car prec-siblings))
(cons
(cons
(if (null? ancestors)
(car prec-siblings)
(draft:make-context
(car prec-siblings) ancestors))
vacant-num)
res)
res)))
(if
(eq? (car prec-siblings) next) (let ((pos-res
(process-single
(car src)
(cdr src)
(- vacant-num 1))))
(if
(null? pos-res) (list (reverse new-res))
(cons (append
(reverse new-res) (car pos-res))
pos-res)))
(more (cdr prec-siblings)
new-res
(- vacant-num 1)))))))))))
(else (if (null? src) '()
(process-single (car src) (cdr src) vacant-num))))))))
(lambda (node) (let ((nset (reverse (as-nodeset node))))
(if (null? nset) nset
(reverse
(filter (lambda (x) (not (null? x)))
(process-single (car nset) (cdr nset) -1)))))))))