#lang racket/base
(require "myenv.ss"
"errors-and-warnings.rkt"
"util.ss"
"access-remote.ss"
"sxpathlib.ss")
(provide (all-defined-out))
(define xlink:namespace-uri 'http://www.w3.org/1999/xlink)
(define xlink:linkbase-uri "http://www.w3.org/1999/xlink/properties/linkbase")
(define (xlink:make-small-seed mode sxlink-arcs sxpointer stack)
(list mode sxlink-arcs sxpointer stack))
(define (xlink:make-full-seed mode sxlink-arcs sxpointer stack
locators+resources arcs declared-labels)
(list mode sxlink-arcs sxpointer stack
locators+resources arcs declared-labels))
(define (xlink:seed-mode seed)
(car seed))
(define (xlink:seed-sxlink-arcs seed)
(cadr seed))
(define (xlink:seed-sxpointer seed)
(list-ref seed 2))
(define (xlink:seed-stack seed)
(list-ref seed 3))
(define (xlink:seed-locators+resources seed)
(list-ref seed 4))
(define (xlink:seed-arcs seed)
(list-ref seed 5))
(define (xlink:seed-declared-labels seed)
(list-ref seed 6))
(define (xlink:add-simple
xlink-values element position sxpointer sxlink-arcs)
(let ((href (xlink:values-href xlink-values))
(role (xlink:values-role xlink-values))
(arcrole (xlink:values-arcrole xlink-values))
(title (xlink:values-title xlink-values))
(show (xlink:values-show xlink-values))
(actuate (xlink:values-actuate xlink-values)))
(if
(not href) sxlink-arcs (call-with-values
(lambda ()
(let ((lst (string-split href (list #\#) 2)))
(cond
((= (length lst) 1) (values (car lst) #f))
((= (string-length (car lst)) 0) (values #f (cadr lst)))
(else
(values (car lst) (cadr lst))))))
(lambda (uri-ending fragment)
(cons
`(,(if (equal? arcrole xlink:linkbase-uri)
'linkbase 'simple)
(from
(uri) (nodes ,element)
(xpointer ,(xlink:sxpointer->childseq sxpointer)))
(to
(uri ,@(if uri-ending (list uri-ending) '()))
,@(if fragment `((xpointer ,fragment)) '())
,@(if role `((role ,role)) '())
,@(if title `((title ,title)) '()))
,@(if arcrole `((arcrole ,arcrole)) '())
,@(if show `((show ,show)) '())
,@(if actuate `((actuate ,actuate)) '())
(declaration
(uri) (nodes ,element)
(xpointer ,(xlink:sxpointer->childseq sxpointer))
(position ,position)))
sxlink-arcs))))))
(define (xlink:add-extended
locators+resources arcs sxlink-arcs declaration)
(let ( (map-join
(lambda (func arg-lst1 arg-lst2)
(let ((arg-lst1 (reverse arg-lst1)))
(let iterate-second ((lst2 (reverse arg-lst2))
(res '()))
(if
(null? lst2) res
(let iterate-first ((lst1 arg-lst1)
(res res))
(if
(null? lst1) (iterate-second (cdr lst2) res)
(iterate-first
(cdr lst1)
(cons (func (car lst1) (car lst2)) res)))))))))
(resource?
(lambda (locator-or-resource)
(assq 'nodes (xlink:resource-data locator-or-resource)))))
(let loop ((arcs arcs)
(sxlink-arcs sxlink-arcs))
(if
(null? arcs) sxlink-arcs
(loop
(cdr arcs)
(let ((arc-info (car arcs)))
(append
(map-join
(lambda (starting ending)
`(,(cond ((xlink:arc-info-linkbase arc-info)
'linkbase)
((and (resource? starting)
(not (resource? ending)))
'outbound)
((and (not (resource? starting))
(resource? ending))
'inbound)
((and (resource? starting) (resource? ending))
'local-to-local)
(else
'third-party))
(from ,@(xlink:resource-data starting))
(to ,@(xlink:resource-data ending))
,@(xlink:arc-info-data arc-info)
,declaration))
(let ((from (xlink:arc-info-from arc-info)))
(if
(not from) locators+resources
(filter
(lambda (locator-or-resource)
(equal? from
(xlink:resource-label locator-or-resource)))
locators+resources)))
(let ((to (xlink:arc-info-to arc-info)))
(if
(not to) locators+resources
(filter
(lambda (locator-or-resource)
(equal? to
(xlink:resource-label locator-or-resource)))
locators+resources))))
sxlink-arcs)))))))
(define (xlink:sxpointer->childseq sxpointer)
(apply
string-append
(map
(lambda (num) (string-append "/" (number->string num)))
(reverse sxpointer))))
(define (xlink:sxpointer4sibling sxpointer)
(cons (+ 1 (car sxpointer)) (cdr sxpointer)))
(define (xlink:make-locator-or-resource label resource-info)
(list label resource-info))
(define (xlink:resource-label locator-or-resource)
(car locator-or-resource))
(define (xlink:resource-data locator-or-resource)
(cadr locator-or-resource))
(define (xlink:add-locator xlink-values position element locators+resources)
(let ((href (xlink:values-href xlink-values))
(role (xlink:values-role xlink-values))
(title (xlink:values-title xlink-values))
(label (xlink:values-label xlink-values)))
(cond
((not href)
(xlink:parser-error
position "locator element doesn't have an xlink:href attribute")
locators+resources)
(else
(let ((lst (string-split href (list #\#) 2)))
(call-with-values
(lambda ()
(cond
((= (length lst) 1) (values (car lst) #f))
((= (string-length (car lst)) 0) (values #f (cadr lst)))
(else (values (car lst) (cadr lst)))))
(lambda (uri fragment)
(cons
(xlink:make-locator-or-resource
label
`((uri ,@(if uri (list uri) '()))
,@(if fragment `((xpointer ,fragment)) '())
,@(if role `((role ,role)) '())
,@(if title `((title ,title)) '())))
locators+resources))))))))
(define (xlink:add-resource xlink-values element sxpointer locators+resources)
(let ((role (xlink:values-role xlink-values))
(label (xlink:values-label xlink-values))
(title (xlink:values-title xlink-values)))
(cons
(xlink:make-locator-or-resource
label
`((uri)
(nodes ,element)
(xpointer ,(xlink:sxpointer->childseq sxpointer))
,@(if role `((role ,role)) '())
,@(if title `((title ,title)) '())))
locators+resources)))
(define (xlink:make-arc-info from to linkbase position data)
(list from to linkbase position data))
(define (xlink:arc-info-from arc-info)
(car arc-info))
(define (xlink:arc-info-to arc-info)
(cadr arc-info))
(define (xlink:arc-info-linkbase arc-info)
(list-ref arc-info 2))
(define (xlink:arc-info-position arc-info)
(list-ref arc-info 3))
(define (xlink:arc-info-data arc-info)
(list-ref arc-info 4))
(define (xlink:add-arc xlink-values position element arcs)
(let ((arcrole (xlink:values-arcrole xlink-values))
(title (xlink:values-title xlink-values))
(show (xlink:values-show xlink-values))
(actuate (xlink:values-actuate xlink-values))
(from (xlink:values-from xlink-values))
(to (xlink:values-to xlink-values)))
(let loop ((as arcs))
(if
(null? as)
(cons
(xlink:make-arc-info
from to
(equal? arcrole xlink:linkbase-uri)
position
`(,@(if arcrole `((arcrole ,arcrole)) '())
,@(if title `((title ,title)) '())
,@(if show `((show ,show)) '())
,@(if actuate `((actuate ,actuate)) '())))
arcs)
(let ((from2 (xlink:arc-info-from (car as)))
(to2 (xlink:arc-info-to (car as))))
(when
(and (or (not from) (not from2) (equal? from from2))
(or (not to) (not to2) (equal? to to2)))
(xlink:parser-error position "duplicate arcs - xlink:from"
(if from (string-append "=" from) " - omitted")
", xlink:to"
(if to (string-append "=" to) " - omitted")))
(loop (cdr as)))))))
(define (xlink:add-default-arc element arcs)
(if (null? arcs)
(list (xlink:make-arc-info
#f #f #f
0 '() ))
arcs))
(define (xlink:add-declared-label xlink-values declared-labels)
(let((label (xlink:values-label xlink-values)))
(if(not label)
declared-labels
(cons label declared-labels))))
(define (xlink:all-labels-declared arcs declared-labels)
(let loop ((arcs arcs))
(if
(null? arcs)
#t
(let((arc-info (car arcs)))
(let((from (xlink:arc-info-from arc-info))
(to (xlink:arc-info-to arc-info))
(position (xlink:arc-info-position arc-info)))
(when (and from (not (member from declared-labels)))
(xlink:parser-error position "label not defined - xlink:from=" from))
(when (and to (not (member to declared-labels)))
(xlink:parser-error position "label not defined - xlink:to=" to))
(loop (cdr arcs)))))))
(define (xlink:construct-xlink-values
type href role arcrole title show actuate label from to)
(list type href role arcrole title show actuate label from to))
(define (xlink:values-type xlink-values)
(car xlink-values))
(define (xlink:values-href xlink-values)
(cadr xlink-values))
(define (xlink:values-role xlink-values)
(list-ref xlink-values 2))
(define (xlink:values-arcrole xlink-values)
(list-ref xlink-values 3))
(define (xlink:values-title xlink-values)
(list-ref xlink-values 4))
(define (xlink:values-show xlink-values)
(list-ref xlink-values 5))
(define (xlink:values-actuate xlink-values)
(list-ref xlink-values 6))
(define (xlink:values-label xlink-values)
(list-ref xlink-values 7))
(define (xlink:values-from xlink-values)
(list-ref xlink-values 8))
(define (xlink:values-to xlink-values)
(list-ref xlink-values 9))
(define (xlink:read-attributes attributes namespaces)
(let loop ((attributes attributes)
(type #f) (href #f) (role #f) (arcrole #f) (title #f) (show #f)
(actuate #f) (label #f) (from #f) (to #f))
(if(null? attributes) (xlink:construct-xlink-values
type href role arcrole title show actuate label from to)
(let ((attribute (car attributes)))
(if
(not (pair? (car attribute))) (loop (cdr attributes)
type href role arcrole title show actuate label from to)
(let ((namespace-prefix (caar attribute))
(attribute-name (cdar attribute))
(attribute-value (cdr attribute)))
(let ((namespace-uri
(let rpt ((ns namespaces))
(cond
((null? ns) namespace-prefix)
((equal? (cadar ns) namespace-prefix) (cddar ns))
(else (rpt (cdr ns)))))))
(if
(not (equal? namespace-uri xlink:namespace-uri))
(loop (cdr attributes)
type href role arcrole title show actuate label from to)
(case attribute-name
((type) (loop (cdr attributes) attribute-value href role
arcrole title show actuate label from to))
((href) (loop (cdr attributes) type attribute-value role
arcrole title show actuate label from to))
((role) (loop (cdr attributes) type href attribute-value
arcrole title show actuate label from to))
((arcrole)
(loop (cdr attributes) type href role attribute-value title
show actuate label from to))
((title) (loop (cdr attributes) type href role arcrole
attribute-value show actuate label from to))
((show) (loop (cdr attributes) type href role arcrole title
attribute-value actuate label from to))
((actuate) (loop (cdr attributes) type href role arcrole
title show attribute-value label from to))
((label) (loop (cdr attributes) type href role arcrole title
show actuate attribute-value from to))
((from) (loop (cdr attributes) type href role arcrole title
show actuate label attribute-value to))
((to) (loop (cdr attributes) type href role arcrole title
show actuate label from attribute-value))
(else (loop (cdr attributes) type href role arcrole title
show actuate label from to)))))))))))
(define (xlink:read-SXML-attributes element ns-prefixes)
(let ((attr-node ((select-kids (ntype?? '@)) element)))
(if
(null? attr-node) (xlink:construct-xlink-values #f #f #f #f #f #f #f #f #f #f)
(let loop ((attr-list (cdar attr-node))
(type #f) (href #f) (role #f) (arcrole #f) (title #f)
(show #f) (actuate #f) (label #f) (from #f) (to #f))
(if
(null? attr-list)
(xlink:construct-xlink-values
type href role arcrole title show actuate label from to)
(let ((attribute-name (symbol->string (caar attr-list)))
(attribute-value (cadar attr-list)))
(call-with-values
(lambda ()
(cond
((string-rindex attribute-name #\:)
=> (lambda (pos)
(values
(string->symbol (substring attribute-name 0 pos))
(string->symbol
(substring attribute-name (+ pos 1)
(string-length attribute-name))))))
(else
(values #f attribute-name))))
(lambda (prefix local)
(if
(not prefix) (loop (cdr attr-list)
type href role arcrole title show actuate label from to)
(let ((namespace-uri
(cond
((assoc prefix ns-prefixes)
=> (lambda (pair)
(string->symbol (cadr pair))))
(else
prefix))))
(if
(not (equal? namespace-uri xlink:namespace-uri))
(loop (cdr attr-list)
type href role arcrole title show actuate label from to)
(case local
((type) (loop (cdr attr-list) attribute-value href role
arcrole title show actuate label from to))
((href) (loop (cdr attr-list) type attribute-value role
arcrole title show actuate label from to))
((role) (loop (cdr attr-list) type href attribute-value
arcrole title show actuate label from to))
((arcrole)
(loop (cdr attr-list) type href role attribute-value title
show actuate label from to))
((title) (loop (cdr attr-list) type href role arcrole
attribute-value show actuate label from to))
((show) (loop (cdr attr-list) type href role arcrole title
attribute-value actuate label from to))
((actuate) (loop (cdr attr-list) type href role arcrole title
show attribute-value label from to))
((label) (loop (cdr attr-list) type href role arcrole title
show actuate attribute-value from to))
((from) (loop (cdr attr-list) type href role arcrole title
show actuate label attribute-value to))
((to) (loop (cdr attr-list) type href role arcrole title show
actuate label from attribute-value))
(else (loop (cdr attr-list) type href role arcrole title show
actuate label from to))))))))))))))
(define (xlink:check-helper value valid-xlink-values attr-name position)
(cond
((not value) ) ((not (member value valid-xlink-values))
(xlink:parser-error position "unexpected attribute value - "
attr-name "=" value))
(else #t)))
(define (xlink:check-type-show-actuate-constraints xlink-values position)
(xlink:check-helper (xlink:values-type xlink-values)
'("simple" "extended" "locator" "arc" "resource"
"title" "none")
"xlink:type"
position)
(xlink:check-helper (xlink:values-show xlink-values)
'("new" "replace" "embed" "other" "none")
"xlink:show"
position)
(xlink:check-helper (xlink:values-actuate xlink-values)
'("onLoad" "onRequest" "other" "none")
"xlink:actuate"
position))
(define (xlink:general-start position xlink-values seed)
(let((sxlink-arcs (xlink:seed-sxlink-arcs seed))
(sxpointer (xlink:seed-sxpointer seed))
(stack (cons (list position xlink-values) (xlink:seed-stack seed))))
(xlink:make-small-seed
'general sxlink-arcs (cons 1 sxpointer) stack)))
(define (xlink:general-end parent-seed seed element)
(let ((mode (xlink:seed-mode parent-seed))
(sxlink-arcs (xlink:seed-sxlink-arcs seed))
(sxpointer
(xlink:sxpointer4sibling (xlink:seed-sxpointer parent-seed)))
(stack (xlink:seed-stack parent-seed)))
(xlink:make-small-seed mode sxlink-arcs sxpointer stack)))
(define (xlink:none-start position xlink-values seed)
(let ((stack (cons (list position xlink-values) (xlink:seed-stack seed))))
(xlink:make-small-seed 'none '() '() stack)))
(define (xlink:none-end parent-seed seed element)
parent-seed)
(define (xlink:simple-start position xlink-values seed)
(let ((stack (cons (list position xlink-values) (xlink:seed-stack seed))))
(xlink:make-small-seed 'none '() '() stack)))
(define (xlink:simple-end parent-seed seed element)
(let ((stack-element (car (xlink:seed-stack seed))))
(let ((position (car stack-element))
(xlink-values (cadr stack-element)))
(let ((mode (xlink:seed-mode parent-seed))
(sxlink-arcs (xlink:add-simple
xlink-values element position
(xlink:seed-sxpointer parent-seed)
(xlink:seed-sxlink-arcs parent-seed)))
(sxpointer
(xlink:sxpointer4sibling (xlink:seed-sxpointer parent-seed)))
(stack (xlink:seed-stack parent-seed)))
(xlink:make-small-seed
mode sxlink-arcs sxpointer stack)))))
(define (xlink:extended-start position xlink-values seed)
(let ((sxlink-arcs (xlink:seed-sxlink-arcs seed))
(sxpointer (cons 1 (xlink:seed-sxpointer seed)))
(stack (cons (list position xlink-values) (xlink:seed-stack seed))))
(xlink:make-full-seed 'extended sxlink-arcs sxpointer stack
'() '() '())))
(define (xlink:extended-end parent-seed seed element)
(let ((stack-element (car (xlink:seed-stack seed))))
(let ((position (car stack-element))
(xlink-values (cadr stack-element)))
(let ((locators+resources (xlink:seed-locators+resources seed))
(arcs (xlink:add-default-arc element (xlink:seed-arcs seed)))
(declared-labels (xlink:seed-declared-labels seed)))
(xlink:all-labels-declared arcs declared-labels)
(let ((mode (xlink:seed-mode parent-seed))
(sxlink-arcs
(xlink:add-extended
locators+resources arcs (xlink:seed-sxlink-arcs seed)
`(declaration
(uri) (nodes ,element)
(xpointer ,(xlink:sxpointer->childseq
(xlink:seed-sxpointer parent-seed)))
(position ,position))))
(sxpointer
(xlink:sxpointer4sibling (xlink:seed-sxpointer parent-seed)))
(stack (xlink:seed-stack parent-seed)))
(xlink:make-small-seed mode sxlink-arcs sxpointer stack))))))
(define (xlink:locator-start position xlink-values seed)
(let ((stack (cons (list position xlink-values) (xlink:seed-stack seed))))
(xlink:make-small-seed 'none '() '() stack)))
(define (xlink:locator-end parent-seed seed element)
(let ((stack-element (car (xlink:seed-stack seed))))
(let ((position (car stack-element))
(xlink-values (cadr stack-element)))
(let ((mode (xlink:seed-mode parent-seed))
(sxlink-arcs (xlink:seed-sxlink-arcs parent-seed))
(sxpointer
(xlink:sxpointer4sibling (xlink:seed-sxpointer parent-seed)))
(stack (xlink:seed-stack parent-seed))
(locators+resources
(xlink:add-locator xlink-values position element
(xlink:seed-locators+resources parent-seed)))
(arcs (xlink:seed-arcs parent-seed))
(declared-labels
(xlink:add-declared-label
xlink-values (xlink:seed-declared-labels parent-seed))))
(xlink:make-full-seed mode sxlink-arcs sxpointer stack
locators+resources arcs declared-labels)))))
(define (xlink:resource-start position xlink-values seed)
(let ((stack (cons (list position xlink-values) (xlink:seed-stack seed))))
(xlink:make-small-seed 'none '() '() stack)))
(define (xlink:resource-end parent-seed seed element)
(let((stack-element (car (xlink:seed-stack seed))))
(let ((position (car stack-element))
(xlink-values (cadr stack-element)))
(let* ((mode (xlink:seed-mode parent-seed))
(sxlink-arcs (xlink:seed-sxlink-arcs parent-seed))
(sxpointer
(xlink:sxpointer4sibling (xlink:seed-sxpointer parent-seed)))
(stack (xlink:seed-stack parent-seed))
(locators+resources
(xlink:add-resource xlink-values element sxpointer
(xlink:seed-locators+resources parent-seed)))
(arcs (xlink:seed-arcs parent-seed))
(declared-labels
(xlink:add-declared-label
xlink-values (xlink:seed-declared-labels parent-seed))))
(xlink:make-full-seed mode sxlink-arcs sxpointer stack
locators+resources arcs declared-labels)))))
(define (xlink:arc-start position xlink-values seed)
(let ((stack (cons (list position xlink-values) (xlink:seed-stack seed))))
(xlink:make-small-seed 'none '() '() stack)))
(define (xlink:arc-end parent-seed seed element)
(let ((stack-element (car (xlink:seed-stack seed))))
(let ((position (car stack-element))
(xlink-values (cadr stack-element)))
(let ((mode (xlink:seed-mode parent-seed))
(sxlink-arcs (xlink:seed-sxlink-arcs parent-seed))
(sxpointer
(xlink:sxpointer4sibling (xlink:seed-sxpointer parent-seed)))
(stack (xlink:seed-stack parent-seed))
(locators+resources (xlink:seed-locators+resources parent-seed))
(arcs (xlink:add-arc xlink-values position element
(xlink:seed-arcs parent-seed)))
(declared-labels
(xlink:seed-declared-labels parent-seed)))
(xlink:make-full-seed mode sxlink-arcs sxpointer stack
locators+resources arcs declared-labels)))))
(define (xlink:get-port-position port)
(string-append "position " (number->string (file-position port))))
(define (xlink:parser-error position . text)
(apply sxml:warn/concat
'XLink "error"
(if (equal? position "unknown")
": "
(format " at ~a: " position))
text))
(define (xlink:branch-helper action-on-branch)
(lambda (document branch-lpath content-nodeset)
(letrec
( (make-new-branch
(lambda (lpath)
(if (null? (cdr lpath)) (cons (car lpath) content-nodeset)
(list (car lpath) (make-new-branch (cdr lpath))))))
(tree-walk
(lambda (elem lpath)
(if
(null? lpath) (action-on-branch elem content-nodeset)
(let loop ((foll-siblings elem)
(prec-siblings '()))
(cond
((null? foll-siblings) (cons*
(car elem)
(make-new-branch lpath)
(cdr elem)))
((and (pair? (car foll-siblings))
(eq? (caar foll-siblings) (car lpath)))
(append
(reverse prec-siblings)
(list
(tree-walk (car foll-siblings) (cdr lpath)))
(cdr foll-siblings)))
(else
(loop (cdr foll-siblings)
(cons (car foll-siblings) prec-siblings)))))))))
(tree-walk document branch-lpath))))
(define xlink:replace-branch
(xlink:branch-helper
(lambda (elem content-nodeset) (cons (car elem) content-nodeset))))
(define xlink:append-branch
(xlink:branch-helper
(lambda (elem content-nodeset) (append elem content-nodeset))))
(define (xlink:get-uri doc)
(let ((nodeset ((select-kids (ntype?? 'uri))
((select-kids (ntype?? '@@)) doc))))
(if (null? nodeset) #f
(cadar nodeset))))
(define (xlink:set-uri-for-sxlink-arcs uri sxlink-arcs)
(letrec
((process-arc
(lambda (node uri-alist)
(case (car node) ((linkbase simple inbound outbound third-party local-to-local
from to declaration)
(call-with-values
(lambda () (process-nodeset (cdr node) uri-alist))
(lambda (new-children new-uri-alist)
(values (cons (car node) new-children)
new-uri-alist))))
((uri)
(cond
((null? (cdr node)) (values `(uri ,uri) uri-alist))
((assoc (cadr node) uri-alist)
=> (lambda (pair)
(values `(uri ,(cdr pair)) uri-alist)))
(else
(let ((resolved-uri
(ar:resolve-uri-according-base uri (cadr node))))
(values `(uri ,resolved-uri)
(cons
(cons (cadr node) resolved-uri)
uri-alist))))))
(else
(values node uri-alist)))))
(process-nodeset
(lambda (nodeset uri-alist)
(let loop ((nset nodeset)
(res '())
(uri-alist uri-alist))
(if
(null? nset)
(values (reverse res) uri-alist)
(call-with-values
(lambda () (process-arc (car nset) uri-alist))
(lambda (new-node new-uri-alist)
(loop (cdr nset)
(cons new-node res)
new-uri-alist))))))))
(call-with-values
(lambda () (process-nodeset sxlink-arcs '()))
(lambda (new-sxlink-arcs dummy)
new-sxlink-arcs))))
(define (xlink:new-level-seed-handler port attributes namespaces seed)
(let ((position (xlink:get-port-position port))
(xlink-values (xlink:read-attributes attributes namespaces)))
(xlink:check-type-show-actuate-constraints xlink-values position)
(let((mode (xlink:seed-mode seed))
(type (xlink:values-type xlink-values)))
(case mode
((general)
(case (if type (string->symbol type) type)
((simple) (xlink:simple-start position xlink-values seed))
((extended) (xlink:extended-start position xlink-values seed))
((none) (xlink:none-start position xlink-values seed))
(else (xlink:general-start position xlink-values seed))))
((extended)
(case (if type (string->symbol type) type)
((locator) (xlink:locator-start position xlink-values seed))
((resource) (xlink:resource-start position xlink-values seed))
((arc) (xlink:arc-start position xlink-values seed))
(else (xlink:none-start position xlink-values seed))))
((none) (xlink:none-start position xlink-values seed))
(else
(xlink:parser-error position "internal processor error - mode="
mode)
(xlink:none-start position xlink-values seed))))))
(define (xlink:finish-element-handler parent-seed seed element)
(let((xlink-values (cadar (xlink:seed-stack seed))))
(let((mode (xlink:seed-mode parent-seed))
(type (xlink:values-type xlink-values)))
(case mode
((general)
(case (if type (string->symbol type) type)
((simple) (xlink:simple-end parent-seed seed element))
((extended) (xlink:extended-end parent-seed
seed element))
((none) (xlink:none-end parent-seed seed element))
(else (xlink:general-end parent-seed seed element))))
((extended)
(case (if type (string->symbol type) type)
((locator) (xlink:locator-end parent-seed
seed element))
((resource) (xlink:resource-end parent-seed
seed element))
((arc) (xlink:arc-end parent-seed seed element))
(else (xlink:none-end parent-seed seed element))))
((none) (xlink:none-end parent-seed seed element))
(else
(xlink:parser-error 0 "internal processor error - mode="
mode)
(xlink:none-end parent-seed seed element))))))
(define (xlink:ending-action xlink:seed)
(let ((sxlink-arcs (reverse (xlink:seed-sxlink-arcs xlink:seed))))
`(sxlink
(declared-here ,@sxlink-arcs))))
(define (SXML->SXML+xlink document)
(letrec
((fold-ts
(lambda (node ns-prefixes seed)
(let ((xlink-values (xlink:read-SXML-attributes node ns-prefixes)))
(let ((mode (xlink:seed-mode seed))
(type (xlink:values-type xlink-values))
(pos "unknown"))
(let rpt
((kids ((select-kids (ntype?? '*)) node))
(new-seed
(case mode
((general)
(case (if type (string->symbol type) type)
((simple)
(xlink:simple-start pos xlink-values seed))
((extended)
(xlink:extended-start pos xlink-values seed))
((none)
(xlink:none-start pos xlink-values seed))
(else
(xlink:general-start pos xlink-values seed))))
((extended)
(case (if type (string->symbol type) type)
((locator)
(xlink:locator-start pos xlink-values seed))
((resource)
(xlink:resource-start pos xlink-values seed))
((arc)
(xlink:arc-start pos xlink-values seed))
(else
(xlink:none-start pos xlink-values seed))))
((none)
(xlink:none-start pos xlink-values seed))
(else
(xlink:parser-error pos "internal processor error - mode=" mode)
(xlink:none-start pos xlink-values seed)))))
(if
(not (null? kids))
(rpt (cdr kids)
(fold-ts (car kids) ns-prefixes new-seed))
(case mode
((general)
(case (if type (string->symbol type) type)
((simple) (xlink:simple-end seed new-seed node))
((extended) (xlink:extended-end seed new-seed node))
((none) (xlink:none-end seed new-seed node))
(else (xlink:general-end seed new-seed node))))
((extended)
(case (if type (string->symbol type) type)
((locator) (xlink:locator-end seed new-seed node))
((resource) (xlink:resource-end seed new-seed node))
((arc) (xlink:arc-end seed new-seed node))
(else (xlink:none-end seed new-seed node))))
((none) (xlink:none-end seed new-seed node))
(else
(xlink:parser-error pos
"internal processor error - mode=" mode)
(xlink:none-end seed new-seed node))))))))))
(let* ((ns-prefixes
(let ((ns-node ((select-kids (ntype?? '*NAMESPACES*))
((select-kids (ntype?? '@@)) document))))
(if (null? ns-node)
'()
(cdar ns-node))))
(sxlink-arcs
(xlink:seed-sxlink-arcs
(fold-ts ((select-kids (ntype?? '*)) document)
ns-prefixes
(xlink:make-small-seed 'general '() '(1) '()))))
(uri (xlink:get-uri document)))
(xlink:append-branch
document
'(@@ sxlink declared-here)
(if uri (xlink:set-uri-for-sxlink-arcs uri sxlink-arcs)
sxlink-arcs)))))
(define (SHTML->SHTML+xlink document)
(letrec
((tree-walk
(lambda (node sxpointer)
(let loop
((sxlink-arcs
(if
(not (and (pair? node) (eq? (car node) 'a)))
'() (let ((href ((select-kids (ntype?? '*text*))
((select-kids (ntype?? 'href))
((select-kids (ntype?? '@)) node)))))
(if
(null? href) '()
(call-with-values
(lambda ()
(let ((lst (string-split (car href) (list #\#) 2)))
(cond
((null? lst) (values (car href) #f))
((= (length lst) 1) (values (car lst) #f))
((= (string-length (car lst)) 0)
(values #f (cadr lst)))
(else
(values (car lst) (cadr lst))))))
(lambda (uri-ending fragment)
`((simple
(from
(uri) (nodes ,node)
(xpointer ,(xlink:sxpointer->childseq sxpointer)))
(to
(uri ,@(if uri-ending (list uri-ending) '()))
,@(if fragment
`((xpointer
,(string-append
"xpointer(descendant::*[a/@name='"
fragment "'])")))
'()))
(declaration
(uri)
(nodes ,node)
(xpointer
,(xlink:sxpointer->childseq sxpointer))))))
)))))
(kids ((select-kids (ntype?? '*)) node))
(kid-pos 1))
(if (null? kids) sxlink-arcs
(loop
(append sxlink-arcs
(tree-walk (car kids) (cons kid-pos sxpointer)))
(cdr kids)
(+ kid-pos 1)))))))
(let ((sxlink-arcs (tree-walk document '()))
(uri (xlink:get-uri document)))
(xlink:append-branch
document
'(@@ sxlink declared-here)
(if uri (xlink:set-uri-for-sxlink-arcs uri sxlink-arcs)
sxlink-arcs)))))