summaryrefslogtreecommitdiff
path: root/ebus-racket/ebus/xexpr-path/main.rkt
diff options
context:
space:
mode:
authorEbus-at-dockstar <ebus@dockstar>2014-07-25 22:13:55 +0200
committerEbus-at-dockstar <ebus@dockstar>2014-07-25 22:13:55 +0200
commitf6675ccdd7a5997def3c4656f0e2c5dbbbed1fc8 (patch)
tree893a37289de684b95a6184c528e5c9c8547e7197 /ebus-racket/ebus/xexpr-path/main.rkt
parentcfb0c10631bbbd31b525e7992b59de06d3c2e550 (diff)
downloadebus-alt-f6675ccdd7a5997def3c4656f0e2c5dbbbed1fc8.tar.gz
ebus-alt-f6675ccdd7a5997def3c4656f0e2c5dbbbed1fc8.zip
embed xexpr-path
Diffstat (limited to 'ebus-racket/ebus/xexpr-path/main.rkt')
-rw-r--r--ebus-racket/ebus/xexpr-path/main.rkt99
1 files changed, 99 insertions, 0 deletions
diff --git a/ebus-racket/ebus/xexpr-path/main.rkt b/ebus-racket/ebus/xexpr-path/main.rkt
new file mode 100644
index 0000000..97e7f81
--- /dev/null
+++ b/ebus-racket/ebus/xexpr-path/main.rkt
@@ -0,0 +1,99 @@
+#lang racket/base
+;
+; XML-Expression Path Lookup
+;
+
+(require racket/contract
+ racket/string
+ racket/match
+ racket/dict
+ racket/list
+ xml)
+
+(provide xexpr-path-first
+ xexpr-path-list
+ xexpr-path-text
+ xexpr-path/c)
+
+
+(define xexpr-path/c
+ (listof (or/c symbol?
+ (list/c symbol? string?)
+ (list/c symbol?))))
+
+
+(define (children element)
+ (match element
+ ((list tag (list (list name value) ...) children ...)
+ children)
+
+ ((list tag children ...)
+ children)
+
+ (else
+ null)))
+
+
+(define (attr-value?? name value)
+ (lambda (v)
+ (equal? (dict-ref (attributes v) name #f) value)))
+
+
+(define (tag-name?? name)
+ (lambda (v)
+ (or (eq? name '*)
+ (and (pair? v)
+ (eq? (car v) name)))))
+
+
+(define (attributes element)
+ (match element
+ ((list tag (list (list name value) ...) children ...)
+ (for/list ((n (in-list name))
+ (v (in-list value)))
+ (cons n v)))
+
+ (else
+ null)))
+
+
+(define (path-item-procedure item)
+ (match item
+ ((list attr-name attr-value)
+ (lambda (tags)
+ (list (filter (attr-value?? attr-name attr-value) tags))))
+
+ ((list attr-name)
+ (lambda (tags)
+ (list
+ (filter values
+ (for/list ((tag (in-list tags)))
+ (dict-ref (attributes tag) attr-name #f))))))
+
+ (tag-name
+ (lambda (tags)
+ (for/list ((tag (in-list tags)))
+ (filter (tag-name?? tag-name) (children tag)))))))
+
+
+(define/contract (xexpr-path-list path xexpr)
+ (-> xexpr-path/c xexpr/c (listof (or/c xexpr/c string?)))
+ (let ((pipeline (append* (for/list ((item (in-list path)))
+ (list (path-item-procedure item) append*)))))
+ ((apply compose (reverse pipeline)) (list xexpr))))
+
+
+(define/contract (xexpr-path-first path xexpr)
+ (-> xexpr-path/c xexpr/c (or/c xexpr/c string? #f))
+ (let ((results (xexpr-path-list path xexpr)))
+ (and (not (null? results))
+ (first results))))
+
+
+(define/contract (xexpr-path-text path xexpr)
+ (-> xexpr-path/c xexpr/c (or/c #f string?))
+ (let ((results (xexpr-path-list path xexpr)))
+ (string-append* (map xexpr->string results))))
+
+
+; vim:set ts=2 sw=2 et: