#lang scheme/base
(require scheme/match
"depend.ss"
"entity.ss"
)
(define (xexpr-node-name elt)
(if (pair? elt)
(car elt)
#f))
(define (has-xexpr-attrs? xexpr)
(and (pair? xexpr)
(pair? (cdr xexpr))
(list? (cadr xexpr))
(andmap (lambda (kv)
(and (list? kv)
(= 2 (length kv))))
(cadr xexpr))))
(define (xexpr-attrs? attrs (error? #t))
(define (xexpr-attr-errors!)
(if error?
(error 'xexpr-attrs? "invalid xexpr attrs: ~a" attrs)
#f))
(define (helper rest)
(cond ((null? rest) #t)
((and (pair? (car rest))
(symbol? (caar rest))
(pair? (cdar rest))
(string? (cadar rest)))
(helper (cdr rest)))
(else (xexpr-attr-errors!))))
(if (pair? attrs)
(helper attrs)
(xexpr-attr-errors!)))
(define (xexpr-attrs xexpr)
(if (and (pair? xexpr)
(pair? (cdr xexpr))
(xexpr-attrs? (cadr xexpr) #f))
(cadr xexpr)
'()))
(define (xexpr-elements xexpr)
(cond ((has-xexpr-attrs? xexpr) (cddr xexpr))
((pair? xexpr) (cdr xexpr))
(else '())))
(define (xexpr->sxml xexpr)
(cond ((string? xexpr) xexpr)
((or (number? xexpr)
(symbol? xexpr))
(entity->string xexpr))
((cdata? xexpr)
(cdata-string xexpr))
((comment? xexpr)
`(*COMMENT* ,(comment-text xexpr)))
((p-i? xexpr)
`(*PI* ,(p-i-instruction xexpr)))
((pair? xexpr)
(xexpr-element->sxml xexpr))
(else (error 'xexpr->sxml "Unknown type ~a" xexpr))))
(define (xexpr-element->sxml xexpr)
(define (attr-helper attrs)
(if (null? attrs) '()
`((@ . ,attrs))))
`(,(xexpr-node-name xexpr) ,@(attr-helper (xexpr-attrs xexpr))
. ,(map xexpr->sxml (xexpr-elements xexpr))))
(define (sxml->xexpr sxml)
(define (attr-helper sxml)
(if-it (sxml:attr-list-node sxml)
(list (cdr it))
'()))
(cond ((string? sxml) sxml)
((pair? sxml)
(match (car sxml)
('*TOP* (sxml->xexpr (last sxml)))
('*PI* (make-p-i (last sxml)))
('*COMMENT* (make-comment (last sxml)))
(else
`(,(sxml:node-name sxml)
,@(attr-helper sxml)
. ,(map sxml->xexpr (sxml:content-raw sxml))))))
(else (error 'sxml->xexpr "unknown type: ~a" sxml))))
(define (sxml? node)
(and (pair? node)
(symbol? (car node))
))
(provide xexpr-elements
xexpr-node-name
xexpr-attrs
xexpr->sxml
sxml->xexpr
sxml?
)