Skip to content

Instantly share code, notes, and snippets.

@death
Created May 18, 2018 11:23
Show Gist options
  • Save death/4ae8de1d11202faecd2d634190e53d8c to your computer and use it in GitHub Desktop.
Save death/4ae8de1d11202faecd2d634190e53d8c to your computer and use it in GitHub Desktop.
flexml example
(defpackage #:snippets/flexml-test
(:use #:cl)
(:import-from #:hu.dwim.util.flexml))
(defpackage #:rss
(:use)
(:export
#:rss #:channel #:item #:title #:guid #:pubdate #:link #:description
#:language #:node #:category #:copyright #:docs #:lastbuilddate
#:managingeditor #:webmaster #:generator #:image #:url #:width #:height
#:comments))
(in-package #:snippets/flexml-test)
(defclass rss-parser (hu.dwim.util.flexml:builder)
())
(defun make-rss-parser ()
(make-instance 'rss-parser :default-package (find-package :rss)))
(defun parse (rss-content)
(let ((parser (make-rss-parser)))
(cxml:parse rss-content parser)
(hu.dwim.util.flexml:root-of parser)))
(defclass rss:node (hu.dwim.util.flexml:node)
())
(macrolet ((def (&rest names)
`(progn
,@(loop for name in names collecting
`(defclass ,name (rss:node) ())))))
(def rss:rss rss:channel rss:item rss:title rss:guid
rss:pubdate rss:link rss:description rss:language
rss:category rss:copyright rss:docs rss:lastbuilddate
rss:managingeditor rss:webmaster rss:generator
rss:image rss:url rss:width rss:height rss:comments))
(defmethod sax:characters ((parser rss-parser) data)
(unless (every (lambda (char)
(member char '(#\Space #\Tab #\Return #\Linefeed)
:test #'char=))
data)
(call-next-method)))
(defun title (item)
(let ((node (find-if (lambda (x) (typep x 'rss:title)) (hu.dwim.util.flexml:children-of item))))
(elt (hu.dwim.util.flexml:children-of node) 0)))
(defun map-items (fn rss)
(iter:iter
(iter:for channel :in-sequence (hu.dwim.util.flexml:children-of rss))
(iter:iter
(iter:for x :in-sequence (hu.dwim.util.flexml:children-of channel))
(when (typep x 'rss:item)
(funcall fn x)))))
(defmacro do-items ((item-var rss) &body forms)
`(map-items (lambda (,item-var) ,@forms) ,rss))
(defun example (&optional (url "http://www.feedforall.com/sample.xml"))
(let ((content (drakma:http-request url)))
(unless (stringp content)
(setf content (sb-ext:octets-to-string content)))
(do-items (x (parse content))
(format t "~A~%" (title x)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment