xml.location
2020-03-25
This system provides a convenient interface for manipulating XML data. It is inspired by the xmltio library.
Upstream URL
Author
Jan Moringen <jmoringe@techfak.uni-bielefeld.de>
Maintainer
Jan Moringen <jmoringe@techfak.uni-bielefeld.de>
License
LLGPLv3
xml.location README
1Introduction
Thexml.location
system provides manipulation of and a conversionmechanisms for XML data:- Typed, XPath-based location bindings
- Extensible Lisp -> XML and XML -> Lisp conversion
- Creation of XPath-specified XML structures
- Automatic compile-time parsing of XML documents and XPaths
This means, when working with an XML document
<root foo="1 2 3">old text</root>
we can write(let ((document (cxml:parse "<root foo=\"1 2 3\">old text</root>" (stp:make-builder))))
(with-locations (((:name name) "node()")
(text "node()/text()")
((:@ (foo "foo") :type '(list number)) "node()")) document
(setf text "new text"
foo '(4 5))
(values name text foo (stp:serialize document (cxml:make-string-sink)))))
=>
(values
"root"
"new text"
(4 5)
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<root foo=\"4 5\">new text</root>")
2Tutorial
The simplest case of usingxml.location
looks like this:(let ((loc (xml.location:loc "<foo a='1' b='c d'>bar baz</foo>" "node()")))
(values
(xml.location:name loc)
(xml.location:@ loc "a" :type 'integer)
(xml.location:@ loc "b" :type '(list symbol))))
=> (values "foo" 1 (C D))
The first line uses the xml.location:loc
function to construct axml.location:location
object for the document ~<foo a="1" b="cd">bar baz</foo>~ and the XPath node()
. In lines 3 -5, thefollowing things are extracted and returned as Lisp objects:- the name of the root node (using the
xml.location:name
accessor) - the value of the attribute "a", interpreted as
integer
(usingthexml.location:@
attribute accessor) - the value of the attribute "b", interpreted as
list
ofsymbol
s
The accessors xml.location:name
, xml.location:@
and
xml.location:val
are setf
able places:
(let ((loc (xml.location:loc "<foo old-attr='1'/>" "node()[@pred-attr='baz']"
:if-no-match :create)))
(setf (xml.location:@ loc "old-attr" :type 'number) 2
(xml.location:@ loc "new-attr") "foo")
loc)
=> #<(LOCATION 3 MIXINS) node()[@pred-attr='baz'] in <foo new-attr="foo" pred-attr="baz" old-attr="2"/> {FAC7D81}>
Note how :if-no-match :create
causes specified locations to becreated if they do not exist already --- including things specifiedin form of predicates in some cases.In both previous examples, a single xml.location:location
object
was used multiple times. Such cases can be simplified using the
xml.location:with-locations-r/o
and xml.location:with-locations
macros. The former binds variables to values extracted from XML
locations while the latter uses symbol macros to make XML locations
setf
able places:
(xml.location:with-locations
(((:name name) "node()")
(text "bla/text()")
((:@ (my-foo "foo") :type '(list number)) "node()")
((:@ bar) "node()"))
"<bla foo='1 2 4' bar='baz'>foo</bla>"
;; Set values of generalized variables
(setf name "frooble"
my-foo '(5 6)
bar 42
text "bubba")
;; Extract values from generalized variables
(values name my-foo bar text))
=> (values "frooble" (5 6) "42" "bubba")
3TODONamespaces
4Conversion Infrastructure
The core of the conversion infrastructure consists of twooperations:- Lisp -> XML conversion
- XML -> Lisp conversion
4.1TODOLisp to XML conversion
4.2TODOXML to Lisp conversion
4.3Adding Conversions
There are several possible ways to define to/from XML conversionmethods for a type:- Types that have obvious string representations
- Types that require a structured representation
- Types that require a structured representation and have internalstructure that can be represented in several different ways
read
and print
which is often sufficient.For the second kind of type, at least the following two methods have to be defined:
(defmethod ->xml ((value MY-TYPE)
(dest stp:element)
(type t))
"Store VALUE in XML element DEST."
;; actual conversion code
)
(defmethod xml-> ((value stp:element)
(type 'MY-TYPE))
"Retrieve an instance of MY-TYPE from the XML element VALUE."
;; actual conversion code
)