Version: 5.1
XML: Parsing and Writing
Paul Graunke and Jay McCarthy
The xml library provides functions for parsing and
generating XML. XML can be represented as an instance of the
document structure type, or as a kind of S-expression that is
called an X-expression.
The xml library does not provide Document Type
Declaration (DTD) processing, including preservation of DTDs in read documents, or validation.
It also does not expand user-defined entities or read user-defined entities in attributes.
It does not interpret namespaces either.
1 Datatypes
Represents a location in an input stream.
Represents a source location. Other structure types extend
source.
When XML is generated from an input stream by read-xml,
locations are represented by location instances. When XML
structures are generated by xexpr->xml, then locations are
symbols.
Represents an externally defined DTD.
Represents a document type.
Represents a comment.
Represents a processing instruction.
Represents a document prolog.
Represents a document.
Represents an element.
Represents an attribute within an element.
Represents a symbolic or numerical entity.
Represents PCDATA content.
Represents CDATA content.
The string field is assumed to be of the form
<![CDATA[‹content›]]> with proper quoting
of ‹content›. Otherwise, write-xml generates
incorrect output.
(struct | | exn:invalid-xexpr exn:fail (code) | | | #:extra-constructor-name make-exn:invalid-xexpr) |
|
code : any/c |
Raised by
read-xml when an error in the XML input is found.
The following grammar describes expressions that create X-expressions:
xexpr | | = | | string |
| | | | | (list symbol (list (list symbol string) ...) xexpr ...) |
| | | | | (cons symbol (list xexpr ...)) |
| | | | | symbol |
| | | | | exact-nonnegative-integer |
| | | | | cdata |
| | | | | misc |
A string is literal data. When converted to an XML stream,
the characters of the data will be escaped as necessary.
A pair represents an element, optionally with attributes. Each
attribute’s name is represented by a symbol, and its value is
represented by a string.
A symbol represents a symbolic entity. For example,
'nbsp represents .
An exact-nonnegative-integer represents a numeric entity. For example,
#x20 represents .
A cdata is an instance of the cdata structure type,
and a misc is an instance of the comment or
p-i structure types.
A contract that is like
xexpr? except produces a better error message when the value is not an
X-expression.
2 Reading and Writing XML
Reads in an XML document from the given or current input port XML
documents contain exactly one element, raising xml-read:error
if the input stream has zero elements or more than one element.
Malformed xml is reported with source locations in the form
‹l›.‹c›/‹o›, where
‹l›, ‹c›, and ‹o› are the line number, column
number, and next port position, respectively as returned by
port-next-location.
Any non-characters other than eof read from the input-port
appear in the document content. Such special values may appear only
where XML content may. See make-input-port for information
about creating ports that return non-character values.
Example: |
|
'(doc () (bold () "hi") " there!") |
Like
read-xml, except that the reader stops after the single element, rather than attempting to read "miscellaneous" XML content after the element. The document returned by
read-xml/document always has an empty
document-misc.
Reads a single XML element from the port. The next non-whitespace
character read must start an XML element, but the input port can
contain other data after the element.
Writes a document to the given output port, currently ignoring
everything except the document’s root element.
Writes document content to the given output port.
Like
write-xml, but newlines and indentation make the output
more readable, though less technically correct when whitespace is
significant.
Writes an X-expression to the given output port, without using an intermediate
XML document.
3 XML and X-expression Conversions
If this is set to non-false, then
xml->xexpr will allow
non-XML objects, such as other structs, in the content of the converted XML
and leave them in place in the resulting “
X-expression”.
Converts XML represented with a string into an
X-expression.
Some elements should not contain any text, only other tags, except
they often contain whitespace for formating purposes. Given a list of
tag names as
tags and the identity function as
choose,
eliminate-whitespace produces a function
that filters out PCDATA consisting solely of whitespace from those
elements, and it raises an error if any non-whitespace text appears.
Passing in
not as
choose filters all elements which
are not named in the
tags list. Using
(lambda (x) #t) as
choose filters all elements regardless of the
tags
list.
If
v is an
X-expression, the result
#t. Otherwise,
exn:invalid-xexprs is raised, with
the a message of the form “Expected ‹
something›, given
‹
something-else›/” The
code field of the exception
is the part of
v that caused the exception.
Like
validate-expr, except that
success-k is called
on each valid leaf, and
fail-k is called on invalid leaves;
the
fail-k may return a value instead of raising an exception
of otherwise escaping. Results from the leaves are combined with
and to arrive at the final result.
4 Parameters
A parameter that determines whether output functions should use the
<‹tag›/> tag notation instead of
<‹tag›></‹tag›>
for elements that have no content.
When the parameter is set to 'always, the abbreviated
notation is always used. When set of 'never, the abbreviated
notation is never generated. when set to a list of symbols is
provided, tags with names in the list are abbreviated. The default is
'always.
The abbreviated form is the preferred XML notation. However, most
browsers designed for HTML will only properly render XHTML if the
document uses a mixture of the two formats. The
html-empty-tags constant contains the W3 consortium’s
recommended list of XHTML tags that should use the shorthand.
Example: |
|
<html><body bgcolor="red">Hi!<br />Bye!</body></html> |
A parameter that controls whether consecutive whitespace is replaced
by a single space. CDATA sections are not affected. The default is
#f.
A parameter that determines whether comments are preserved or
discarded when reading XML. The default is #f, which
discards comments.
Controls whether
xml->xexpr drops or preserves attribute
sections for an element that has no attributes. The default is
#f, which means that all generated
X-expression
elements have an attributes list (even if it’s empty).
5 PList Library
The xml/plist library provides the ability to read and
write XML documents that conform to the plist DTD, which is
used to store dictionaries of string–value associations. This format
is used by Mac OS X (both the operating system and its applications)
to store all kinds of data.
A plist dictionary is a value that could be created by an
expression matching the following dict-expr grammar:
dict-expr | | = | | (list 'dict assoc-pair ...) |
| | | | |
assoc-pair | | = | | (list 'assoc-pair string pl-value) |
| | | | |
pl-value | | = | | string |
| | | | | (list 'true) |
| | | | | (list 'false) |
| | | | | (list 'integer integer) |
| | | | | (list 'real real) |
| | | | | dict-expr |
| | | | | (list 'array pl-value ...) |
Examples: |
> (define my-dict | `(dict (assoc-pair "first-key" | "just a string with some whitespace") | (assoc-pair "second-key" | (false)) | (assoc-pair "third-key" | (dict)) | (assoc-pair "fourth-key" | (dict (assoc-pair "inner-key" | (real 3.432)))) | (assoc-pair "fifth-key" | (array (integer 14) | "another string" | (true))) | (assoc-pair "sixth-key" | (array)))) |
|
> (define-values (in out) (make-pipe)) |
> (write-plist my-dict out) |
> (close-output-port out) |
> (define new-dict (read-plist in)) |
> (equal? my-dict new-dict) |
#t |
The XML generated by write-plist in the above example
looks like the following, if re-formatted by:
<?xml version="1.0" encoding="UTF-8"?> |
<!DOCTYPE plist SYSTEM |
"file://localhost/System/Library/DTDs/PropertyList.dtd"> |
<plist version="0.9"> |
<dict> |
<key>first-key</key> |
<string>just a string with some whitespace</string> |
<key>second-key</key> |
<false /> |
<key>third-key</key> |
<dict /> |
<key>fourth-key</key> |
<dict> |
<key>inner-key</key> |
<real>3.432</real> |
</dict> |
<key>fifth-key</key> |
<array> |
<integer>14</integer> |
<string>another string</string> |
<true /> |
</array> |
<key>sixth-key</key> |
<array /> |
</dict> |
</plist> |