#lang racket/base (require racket/contract racket/match racket/dict racket/function racket/list xml) (define keyword->symbol (compose string->symbol keyword->string)) (define (se-path/xexpr p x) (match p [(list) (list x)] [(list-rest (? symbol? s) r) (match x [(list-rest (? (curry equal? s)) rs) (se-path/tag-body r rs)] [_ empty])] [_ empty])) (define (se-path/tag-body p x) (match p [(list) (match x [(list) empty] [(list-rest (list (list (? symbol?) (? string?)) ...) rs) (se-path/tag-body p rs)] [(? list?) x] [_ empty])] [(list-rest (? symbol?) _) (match x [(list-rest (list (list (? symbol?) (? string?)) ...) rs) (append-map (curry se-path/xexpr p) rs)] [(? list?) (append-map (curry se-path/xexpr p) x)] [_ empty])] [(list (? keyword? k)) (match x [(list-rest (and attrs (list (list (? symbol?) (? string?)) ...)) rs) (se-path/attr (keyword->symbol k) attrs)] [_ empty])] [_ empty])) (define (se-path/attr k attrs) (dict-ref attrs k empty)) (define (se-path*/list p x) (append (se-path/xexpr p x) (match x [(list (? symbol? tag) (list (list (? symbol?) (? string?)) ...) rs ...) (append-map (curry se-path*/list p) rs)] [(list (? symbol? tag) rs ...) (append-map (curry se-path*/list p) rs)] [_ empty]))) (define (se-path* p x) (match (se-path*/list p x) [(list) #f] [(list-rest f rs) f])) (define se-path? (match-lambda [(list) #t] [(list (? keyword?)) #t] [(list-rest (? symbol?) l) (se-path? l)] [_ #f])) (provide/contract [se-path? contract?] [se-path* (-> se-path? xexpr? ; XXX maybe this shouldn't be any/c any/c)] [se-path*/list (-> se-path? xexpr? ; XXX see above (listof any/c))])