1 SXML
2 SAX Parsing (input)
ssax: xml->sxml
3 Serialization (output)
srl: sxml->xml
srl: sxml->xml-noindent
srl: sxml->html
srl: sxml->html-noindent
4 Search (SXPATH)
sxpath
5 Transformation (SXSLT)
pre-post-order
6 ???
6.1 Automatically Extracted Comments
6.2 ssax.ss
make-xml-token
xml-token?
xml-token-kind
xml-token-head
ssax: read-markup-token
ssax: read-pi-body-as-string
ssax: skip-internal-dtd
ssax: read-cdata-body
ssax: read-char-ref
ssax: handle-parsed-entity
make-empty-attlist
attlist-add
attlist-null?
attlist-remove-top
attliast->alist
attlist-fold
ssax: read-attributes
ssax: uri-string->symbol
ssax: complete-start-tag
ssax: read-external-id
ssax: read-char-data
ssax: assert-token
ssax: make-pi-parser
ssax: make-elem-parser
ssax: make-parser
ssax: reverse-collect-str
6.3 input-parse.ss
parser-error
6.4 sxml-tree-trans.ss
SRV: send-reply
post-order
replace-range: :
6.5 sxml-to-html.ss
SXML->HTML
entag
enattr
string->good HTML
6.6 sxml-to-html-ext.ss
make-header
make-navbar:
make-footer
universal-conversion-rules
universal-protected-rules
alist-conv-rules
7 ???
7.1 Raw Lists of Exported Identifiers
7.2 SSAX-code.rkt
7.3 common.rkt
7.4 myenv.rkt
7.5 util.rkt
7.6 parse-error.rkt
7.7 input-parse.rkt
7.8 look-for-str.rkt
7.9 char-encoding.rkt
7.10 SXML-tree-trans.rkt
7.11 sxpathlib.rkt
7.12 srfi-12.rkt
7.13 mime.rkt
7.14 http.rkt
7.15 access-remote.rkt
7.16 id.rkt
7.17 xlink-parser.rkt
7.18 ssax-prim.rkt
7.19 multi-parser.rkt
7.20 sxml-tools.rkt
7.21 sxpath-ext.rkt
7.22 xpath-parser.rkt
7.23 txpath.rkt
7.24 sxpath.rkt
7.25 xpath-ast.rkt
7.26 xpath-context_ xlink.rkt
7.27 ddo-axes.rkt
7.28 ddo-txpath.rkt
7.29 lazy-xpath.rkt
7.30 lazy-ssax.rkt
7.31 modif.rkt
7.32 serializer.rkt
8 Reporting Bugs

SXML: The S-Expression representation of XML terms

 (require (planet clements/sxml2))
This planet library contains Oleg Kiselyov’s SXML libraries in a Racket-friendly format. It is a direct descendant of Dmitry Lizorkin’s PLaneT package. It’s different from that package in that
  1. It contains some documentation (here it is!),

  2. it contains some tests that run in Racket,

  3. it raises racket exceptions rather than printing to stderr and raising "-1",

  4. it has only one require point (ssax & sxml are both included), and

  5. it doesn’t depend on schemeunit:3, so it compiles quickly.

This documentation is scraped together from various sources; the bulk of it (currently) is pulled from in-source comments.
I’m hoping that this will become a Racket community project, with various people contributing documentation and test cases and maybe even bug fixes.
To that end, this code currently lives in a github repository which should be fairly easy to find. Patches gratefully accepted.
–John Clements, 2011-02-17

1 SXML

SXML is a representation of XML elements using s-expressions. Specifically, an XML element containing some content is represented as an s-expression whose first element is a symbol containing the tag name, and whose remaining elements are the SXML representation of the original content.

To be more specific, the XML element

  <abc>def<ghi />jkl</abc>

corresponds to the SXML value

  '(abc "def" (ghi) "jkl")

XML attributes are represented using an optional second element of the s-expression whose "tag" is "@".

So, the xml element

  <customer specialness="gazonga">Barry White</customer>

corresponds to the XML element

  '(customer (@ (specialness "gazonga")) "Barry White")

That’s the easy part. Things get more icky when you start talking about documents and namespaces.

2 SAX Parsing (input)

(ssax:xml->sxml port    
  namespace-prefix-assig)  sxml?
  port : port?
  namespace-prefix-assig : (listof (cons/c symbol? string?))
Reads a single xml element from the given port, and returns the corresponding sxml representation. The namespace-prefix-assig association list provides shortened forms to be used in place of namespaces.

So, for instance,

  (ssax:xml->sxml
   (open-input-string
    "<zippy><pippy pigtails=\"2\">ab</pippy>cd</zippy>")
   '())

Evaluates to:

  '(*TOP* (zippy (pippy (@ (pigtails "2")) "ab") "cd"))

3 Serialization (output)

(srl:sxml->xml sxml-obj [dest])  (or/c string? unspecified)
  sxml-obj : sxml?
  dest : port-or-filename? = null
Serializes the sxml-obj into XML, with indentation to facilitate readability by a human.

If dest is not supplied, the functions return a string that contains the serialized representation of the sxml-obj. If dest is supplied and is a port, the functions write the serialized representation of sxml-obj to this port and return an unspecified result.

If dest is supplied and is a string, this string is treated as an output filename, the serialized representation of sxml-obj is written to that filename and an unspecified result is returned. If a file with the given name already exists, the effect is unspecified.

(srl:sxml->xml-noindent sxml-obj [dest])
  (or/c string? unspecified)
  sxml-obj : sxml?
  dest : port-or-filename? = null
Serializes the sxml-obj into XML, without indentation.

(srl:sxml->html sxml-obj [dest])  (or/c string? unspecified)
  sxml-obj : sxml?
  dest : port-or-filename? = null
Serializes the sxml-obj into HTML, with indentation to facilitate readability by a human.

If dest is not supplied, the functions return a string that contains the serialized representation of the sxml-obj. If dest is supplied and is a port, the functions write the serialized representation of sxml-obj to this port and return an unspecified result.

If dest is supplied and is a string, this string is treated as an output filename, the serialized representation of sxml-obj is written to that filename and an unspecified result is returned. If a file with the given name already exists, the effect is unspecified.

(srl:sxml->html-noindent sxml-obj [dest])
  (or/c string? unspecified)
  sxml-obj : sxml?
  dest : port-or-filename? = null
Serializes the sxml-obj into HTML, without indentation.

4 Search (SXPATH)

(sxpath path [ns-binding])  procedure?
  path : abbr-sxpath?
  ns-binding : ns-binding? = '()
Given a path, produces a procedure that accepts an sxml document and returns a list of matches. Note that the *TOP* node of the document is required.

AbbrPath is a list. It is translated to the full SXPath according

to the following rewriting rules

(sxpath '()) -> (node-join)

(sxpath '(path-component ...)) ->

        (node-join (sxpath1 path-component) (sxpath '(...)))

(sxpath1 '//) -> (sxml:descendant-or-self sxml:node?)

(sxpath1 '(equal? x)) -> (select-kids (node-equal? x))

(sxpath1 '(eq? x))    -> (select-kids (node-eq? x))

(sxpath1 '(*or* ...))  -> (select-kids (ntype-names??

                                         (cdr '(*or* ...))))

(sxpath1 '(*not* ...)) -> (select-kids (sxml:complement

                                        (ntype-names??

                                         (cdr '(*not* ...)))))

(sxpath1 '(ns-id:* x)) -> (select-kids

                                     (ntype-namespace-id?? x))

(sxpath1 ?symbol)     -> (select-kids (ntype?? ?symbol))

(sxpath1 ?string)     -> (txpath ?string)

(sxpath1 procedure)   -> procedure

(sxpath1 '(?symbol ...)) -> (sxpath1 '((?symbol) ...))

(sxpath1 '(path reducer ...)) ->

        (node-reduce (sxpath path) (sxpathr reducer) ...)

(sxpathr number)      -> (node-pos number)

(sxpathr path-filter) -> (filter (sxpath path-filter))

Examples:

All cells of an html table:

  (define table
    `(*TOP*
      (table
       (tr (td "a") (td "b"))
       (tr (td "c") (td "d")))))
  
  ((sxpath '(table tr td)) table)

... produces:

  '((td "a") (td "b") (td "c") (td "d"))

All cells anywhere in a document:

  (define table
    `(*TOP*
      (div
       (p (table
           (tr (td "a") (td "b"))
           (tr (td "c") (td "d"))))
       (table
        (tr (td "e"))))))
  
  ((sxpath '(// td)) table)

... produces:

  '((td "a") (td "b") (td "c") (td "d") (td "e"))

One result may be nested in another one:

  (define doc
    `(*TOP*
      (div
       (p (div "3")
          (div (div "4"))))))
  
  ((sxpath '(// div)) doc)

... produces:

  '((div (p (div "3") (div (div "4")))) (div "3") (div (div "4")) (div "4"))

There’s also a string-based syntax, txpath. As shown in the grammar above, sxpath assumes that any strings in the path are expressed using the txpath syntax.

So, for instance, the prior example could be rewritten using a string:

  (define doc
    `(*TOP*
      (div
       (p (div "3")
          (div (div "4"))))))
  
  ((sxpath "//div") doc)

... produces:

  '((div (p (div "3") (div (div "4")))) (div "3") (div (div "4")) (div "4"))

More generally, lists in the s-expression syntax correspond to string concatenation in the txpath syntax.

So, to find all italics that appear at top level within a paragraph:

  (define doc
  `(*TOP*
    (div
     (p (i "3")
        (froogy (i "4"))))))
  
  ((sxpath "//p/i") doc)

... produces:

  '((i "3"))

Handling of namespaces in sxpath is a bit surprising. In particular, it appears to me that sxpath’s model is that namespaces must appear fully expanded in the matched source.

For instance, this call:

  ((sxpath "//ns:p" `((ns . "http://example.com")))
  '(*TOP* (html (http://example.com:body
                 (http://example.com:p "first para")
                 (http://example.com:p
                  "second para containing"
                  (http://example.com:p "third para") "inside it")))))

... produces:

  '((http://example.com:p "first para")
                 (http://example.com:p "second para containing"
                                       (http://example.com:p "third para") "inside it")
                 (http://example.com:p "third para"))

But the corresponding example where the source document contains a namespace shortcut does not match in the same way. That is,

  ((sxpath "//ns:p" `((ns . "http://example.com")))
  '(*TOP* (@ (*NAMESPACES* (ns "http://example.com")))
          (html (ns:body (ns:p "first para")
                         (ns:p "second para containing"
                               (ns:p "third para") "inside it")))))

...produces the empty list. Instead, you must pretend that the shortcut is actually the namespace, so that

  ((sxpath "//ns:p" `((ns . "ns")))
  '(*TOP* (@ (*NAMESPACES* (ns "http://example.com")))
          (html (ns:body (ns:p "first para")
                         (ns:p "second para containing"
                               (ns:p "third para") "inside it")))))

... produces:

  '((ns:p "first para")
    (ns:p "second para containing"
          (ns:p "third para") "inside it")
    (ns:p "third para"))

Ah well.

5 Transformation (SXSLT)

(pre-post-order tree bindings)  sxml?
  tree : sxml?
  bindings : (listof binding?)
Pre-Post-order traversal of a tree and creation of a new tree.

<binding> ::= (<trigger-symbol> *preorder* . <handler>) |

              (<trigger-symbol> *macro* . <handler>) |

              (<trigger-symbol> <new-bindings> . <handler>) |

              (<trigger-symbol> . <handler>)

<trigger-symbol> ::= XMLname | *text* | *default*

<handler> :: <trigger-symbol> x [<tree>] -> <new-tree>

The pre-post-order function visits the nodes and nodelists pre-post-order (depth-first). For each <Node> of the form (name <Node> ...) it looks up an association with the given ’name’ among its bindings. If it fails, pre-post-order tries to locate a *default* binding. It’s an error if the latter attempt fails as well. Having found a binding, the pre-post-order function first checks to see if the binding is of the form

  (<trigger-symbol> *preorder* . <handler>)

If it is, the handler is ’applied’ to the current node. Otherwise, the pre-post-order function first calls itself recursively for each child of the current node, with <new-bindings> prepended to the <bindings> in effect. The result of these calls is passed to the <handler> (along with the head of the current <Node>). To be more precise, the handler is _applied_ to the head of the current node and its processed children. The result of the handler, which should also be a <tree>, replaces the current <Node>. If the current <Node> is a text string or other atom, a special binding with a symbol *text* is looked up.

A binding can also be of a form

  (<trigger-symbol> *macro* . <handler>)

This is equivalent to *preorder* described above. However, the result is re-processed again, with the current stylesheet.

A tiny example:

  (require (planet clements/sxml2))
  
  (define sample-doc
    `(*TOP*
      (html (title "the title")
            (body (p "paragraph 1")
                  (p "paragraph 2")))))
  
  (define italicizer
    `((p . ,(lambda (tag . content)
              (cons tag (cons "PARAGRAPH BEGINS: " content))))
      (*text* . ,(lambda (tag content)
                  `(i ,content)))
      (*default* . ,(lambda args args))))
  
  (pre-post-order sample-doc italicizer)

produces:

  '(*TOP*
    (html
     (title (i "the title"))
     (body
      (p "PARAGRAPH BEGINS: " (i "paragraph 1"))
      (p "PARAGRAPH BEGINS: " (i "paragraph 2")))))

6 

6.1 Automatically Extracted Comments

The following "documentation" was generated automatically, using a script that I believe is due to Mike Sperber. This documentation has not been read or formatted for scribble, and should be considered only as raw material for use in creating actual documentation.

6.2 ssax.ss

(make-xml-token KIND HEAD)  ???
  KIND : KIND
  HEAD : HEAD
This creates an XML token.

(xml-token? THING)  ???
  THING : any/c

(xml-token-kind XML-TOKEN)  ???
  XML-TOKEN : symbol?

(xml-token-head XML-TOKEN)  ???
  XML-TOKEN : symbol?

(ssax:read-markup-token PORT)  ???
  PORT : port?
This procedure starts parsing of a markup token. The current position in the stream must be #\<. This procedure scans enough of the input stream to figure out what kind of a markup token it is seeing. The procedure returns an xml-token structure describing the token. Note, generally reading of the current markup is not finished! In particular, no attributes of the start-tag token are scanned.

Here’s a detailed break out of the return values and the position in the PORT when that particular value is returned: PI-token: only PI-target is read. To finish the Processing Instruction and disregard it, call ssax:skip-pi. ssax:read-attributes may be useful as well (for PIs whose content is attribute-value pairs) END-token: The end tag is read completely; the current position is right after the terminating #\> character. COMMENT is read and skipped completely. The current position is right after "–>" that terminates the comment. CDSECT The current position is right after "<!CDATA[" Use ssax:read-cdata-body to read the rest. DECL We have read the keyword (the one that follows "<!") identifying this declaration markup. The current position is after the keyword (usually a whitespace character)

START-token We have read the keyword (GI) of this start tag. No attributes are scanned yet. We don’t know if this tag has an empty content either. Use ssax:complete-start-tag to finish parsing of the token.

(ssax:read-pi-body-as-string PORT)  ???
  PORT : port?
The current position is right after reading the PITarget. We read the body of PI and return is as a string. The port will point to the character right after ’?>’ combination that terminates PI. [16] PI ::= ’<?’ PITarget (S (Char* - (Char* ’?>’ Char*)))? ’?>’

(ssax:skip-internal-dtd PORT)  ???
  PORT : port?
The current pos in the port is inside an internal DTD subset (e.g., after reading #\[ that begins an internal DTD subset) Skip until the "]>" combination that terminates this DTD

(ssax:read-cdata-body PORT STR-HANDLER SEED)  ???
  PORT : port?
  STR-HANDLER : procedure?
  SEED : SEED
This procedure must be called after we have read a string "<![CDATA[" that begins a CDATA section. The current position must be the first position of the CDATA body. This function reads _lines_ of the CDATA body and passes them to a STR-HANDLER, a character data consumer.

The str-handler is a STR-HANDLER, a procedure STRING1 STRING2 SEED. The first STRING1 argument to STR-HANDLER never contains a newline. The second STRING2 argument often will. On the first invocation of the STR-HANDLER, the seed is the one passed to ssax:read-cdata-body as the third argument. The result of this first invocation will be passed as the seed argument to the second invocation of the line consumer, and so on. The result of the last invocation of the STR-HANDLER is returned by the ssax:read-cdata-body. Note a similarity to the fundamental ’fold’ iterator.

Within a CDATA section all characters are taken at their face value, with only three exceptions: CR, LF, and CRLF are treated as line delimiters, and passed as a single #\newline to the STR-HANDLER "]]>" combination is the end of the CDATA section. &gt; is treated as an embedded #\> character Note, &lt; and &amp; are not specially recognized (and are not expanded)!

(ssax:read-char-ref PORT)  ???
  PORT : port?
[66] CharRef ::= ’&#’ [0-9]+ ’;’ | ’&#x’ [0-9a-fA-F]+ ’;’

This procedure must be called after we we have read "&#" that introduces a char reference. The procedure reads this reference and returns the corresponding char The current position in PORT will be after ";" that terminates the char reference Faults detected: WFC: XML-Spec.html#wf-Legalchar

According to Section "4.1 Character and Entity References" of the XML Recommendation: "[Definition: A character reference refers to a specific character in the ISO/IEC 10646 character set, for example one not directly accessible from available input devices.]" Therefore, we use a ucscode->char function to convert a character code into the character – *regardless* of the current character encoding of the input stream.

(ssax:handle-parsed-entity PORT    
  NAME    
  ENTITIES)  ???
  PORT : port?
  NAME : ???
  ENTITIES : ???
CONTENT-HANDLER [STR-HANDLER procedure?] SEED

Expand and handle a parsed-entity reference port - a PORT name - the name of the parsed entity to expand, a symbol entities - see ENTITIES content-handler – procedure PORT ENTITIES SEED that is supposed to return a SEED str-handler - a STR-HANDLER. It is called if the entity in question turns out to be a pre-declared entity

The result is the one returned by CONTENT-HANDLER or STR-HANDLER Faults detected: WFC: XML-Spec.html#wf-entdeclared WFC: XML-Spec.html#norecursion

(make-empty-attlist)  ???
The ATTLIST Abstract Data Type Currently is implemented as an assoc list sorted in the ascending order of NAMES.

(attlist-add ATTLIST NAME-VALUE-PAIR)  ???
  ATTLIST : ???
  NAME-VALUE-PAIR : ???
Add a name-value pair to the existing attlist preserving the order Return the new list, in the sorted ascending order. Return #f if a pair with the same name already exists in the attlist

(attlist-null? ATTLIST)  ???
  ATTLIST : ???

(attlist-remove-top ATTLIST)  ???
  ATTLIST : ???
Given an non-null attlist, return a pair of values: the top and the rest

(attliast->alist)  ???

(attlist-fold)  ???

(ssax:read-attributes PORT ENTITIES)  ???
  PORT : port?
  ENTITIES : ???
This procedure reads and parses a production Attribute* [41] Attribute ::= Name Eq AttValue [10] AttValue ::= ’"’ ([^<&"] | Reference)* ’"’ | "’" ([^<&’] | Reference)* "’" [25] Eq ::= S? ’=’ S?

The procedure returns an ATTLIST, of Name (as UNRES-NAME), Value (as string) pairs. The current character on the PORT is a non-whitespace character that is not an ncname-starting character.

Note the following rules to keep in mind when reading an ’AttValue’ "Before the value of an attribute is passed to the application or checked for validity, the XML processor must normalize it as follows: - a character reference is processed by appending the referenced character to the attribute value - an entity reference is processed by recursively processing the replacement text of the entity [see ENTITIES] [named entities amp lt gt quot apos are assumed pre-declared] - a whitespace character (#x20, #xD, #xA, #x9) is processed by appending #x20 to the normalized value, except that only a single #x20 is appended for a "#xD#xA" sequence that is part of an external parsed entity or the literal entity value of an internal parsed entity - other characters are processed by appending them to the normalized value "

Faults detected: WFC: XML-Spec.html#CleanAttrVals WFC: XML-Spec.html#uniqattspec

(ssax:uri-string->symbol URI-STR)  ???
  URI-STR : string?
Convert a URI-STR to an appropriate symbol

(ssax:complete-start-tag TAG    
  PORT    
  ELEMS    
  ENTITIES    
  NAMESPACES)  ???
  TAG : symbol?
  PORT : port?
  ELEMS : ???
  ENTITIES : ???
  NAMESPACES : ???
This procedure is to complete parsing of a start-tag markup. The procedure must be called after the start tag token has been read. TAG is an UNRES-NAME. ELEMS is an instance of xml-decl::elems; it can be #f to tell the function to do _no_ validation of elements and their attributes.

This procedure returns several values: ELEM-GI: a RES-NAME. ATTRIBUTES: element’s attributes, an ATTLIST of (RES-NAME . STRING) pairs. The list does NOT include xmlns attributes. NAMESPACES: the input list of namespaces amended with namespace (re-)declarations contained within the start-tag under parsing ELEM-CONTENT-MODEL

On exit, the current position in PORT will be the first character after #\> that terminates the start-tag markup.

Faults detected: VC: XML-Spec.html#enum VC: XML-Spec.html#RequiredAttr VC: XML-Spec.html#FixedAttr VC: XML-Spec.html#ValueType WFC: XML-Spec.html#uniqattspec (after namespaces prefixes are resolved) VC: XML-Spec.html#elementvalid WFC: REC-xml-names/#dt-NSName

Note, although XML Recommendation does not explicitly say it, xmlns and xmlns: attributes don’t have to be declared (although they can be declared, to specify their default value)

Procedure: ssax:complete-start-tag tag-head port elems entities namespaces

(ssax:read-external-id PORT)  ???
  PORT : port?
This procedure parses an ExternalID production:

[75] ExternalID ::= 'SYSTEM' S SystemLiteral

        | 'PUBLIC' S PubidLiteral S SystemLiteral

[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")

[12] PubidLiteral ::=  '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"

[13] PubidChar ::=  #x20 | #xD | #xA | [a-zA-Z0-9]

                        | [-'()+,./:=?;!*#@$_%]

This procedure is supposed to be called when an ExternalID is expected; that is, the current character must be either #\S or #\P that start correspondingly a SYSTEM or PUBLIC token. This procedure returns the SystemLiteral as a string. A PubidLiteral is disregarded if present.

(ssax:read-char-data PORT    
  EXPECT-EOF?    
  STR-HANDLER    
  SEED)  ???
  PORT : port?
  EXPECT-EOF? : boolean?
  STR-HANDLER : procedure?
  SEED : ???
This procedure is to read the character content of an XML document or an XML element. [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)* To be more precise, the procedure reads CharData, expands CDSect and character entities, and skips comments. The procedure stops at a named reference, EOF, at the beginning of a PI or a start/end tag.

port a PORT to read expect-eof? a boolean indicating if EOF is normal, i.e., the character data may be terminated by the EOF. EOF is normal while processing a parsed entity. str-handler a STR-HANDLER seed an argument passed to the first invocation of STR-HANDLER.

The procedure returns two results: SEED and TOKEN. The SEED is the result of the last invocation of STR-HANDLER, or the original seed if STR-HANDLER was never called.

TOKEN can be either an eof-object (this can happen only if expect-eof? was #t), or: - an xml-token describing a START tag or an END-tag; For a start token, the caller has to finish reading it. - an xml-token describing the beginning of a PI. It’s up to an application to read or skip through the rest of this PI; - an xml-token describing a named entity reference.

CDATA sections and character references are expanded inline and never returned. Comments are silently disregarded.

As the XML Recommendation requires, all whitespace in character data must be preserved. However, a CR character (#xD) must be disregarded if it appears before a LF character (#xA), or replaced by a #xA character otherwise. See Secs. 2.10 and 2.11 of the XML Recommendation. See also the canonical XML Recommendation.

(ssax:assert-token TOKEN KIND GI)  ???
  TOKEN : ???
  KIND : ???
  GI : ???
Make sure that TOKEN is of anticipated KIND and has anticipated GI Note GI argument may actually be a pair of two symbols, Namespace URI or the prefix, and of the localname. If the assertion fails, error-cont is evaluated by passing it three arguments: token kind gi. The result of error-cont is returned.

(ssax:make-pi-parser my-pi-handlers)  ???
  my-pi-handlers : ???
Create a parser to parse and process one Processing Element (PI).

my-pi-handlers An assoc list of pairs (PI-TAG . PI-HANDLER) where PI-TAG is an NCName symbol, the PI target, and PI-HANDLER is a procedure PORT PI-TAG SEED where PORT points to the first symbol after the PI target. The handler should read the rest of the PI up to and including the combination ’?>’ that terminates the PI. The handler should return a new seed. One of the PI-TAGs may be the symbol *DEFAULT*. The corresponding handler will handle PIs that no other handler will. If the *DEFAULT* PI-TAG is not specified, ssax:make-pi-parser will assume the default handler that skips the body of the PI

The output of the ssax:make-pi-parser is a procedure PORT PI-TAG SEED that will parse the current PI according to the user-specified handlers.

The previous version of ssax:make-pi-parser was a low-level macro:
  (define-macro ssax:make-pi-parser
    (lambda (my-pi-handlers)
    `(lambda (port target seed)
      (case target
  
        ,@(let loop ((pi-handlers my-pi-handlers) (default #f))
           (cond
            ((null? pi-handlers)
             (if default `((else (,default port target seed)))
                 '((else
                    (ssax:warn port "Skipping PI: " target nl)
                    (ssax:skip-pi port)
                    seed))))
            ((eq? '*DEFAULT* (caar pi-handlers))
             (loop (cdr pi-handlers) (cdar pi-handlers)))
            (else
             (cons
              `((,(caar pi-handlers)) (,(cdar pi-handlers) port target seed))
              (loop (cdr pi-handlers) default)))))))))

(ssax:make-elem-parser my-new-level-seed    
  my-finish-element)  ???
  my-new-level-seed : ???
  my-finish-element : ???
my-char-data-handler my-pi-handlers

Create a parser to parse and process one element, including its character content or children elements. The parser is typically applied to the root element of a document.

my-new-level-seed procedure ELEM-GI ATTRIBUTES NAMESPACES EXPECTED-CONTENT SEED where ELEM-GI is a RES-NAME of the element about to be processed. This procedure is to generate the seed to be passed to handlers that process the content of the element. This is the function identified as ’fdown’ in the denotational semantics of the XML parser given in the title comments to this file.

my-finish-element procedure ELEM-GI ATTRIBUTES NAMESPACES PARENT-SEED SEED This procedure is called when parsing of ELEM-GI is finished. The SEED is the result from the last content parser (or from my-new-level-seed if the element has the empty content). PARENT-SEED is the same seed as was passed to my-new-level-seed. The procedure is to generate a seed that will be the result of the element parser. This is the function identified as ’fup’ in the denotational semantics of the XML parser given in the title comments to this file.

my-char-data-handler A STR-HANDLER

my-pi-handlers See ssax:make-pi-handler above

The generated parser is a procedure START-TAG-HEAD PORT ELEMS ENTITIES NAMESPACES PRESERVE-WS? SEED The procedure must be called after the start tag token has been read. START-TAG-HEAD is an UNRES-NAME from the start-element tag. ELEMS is an instance of xml-decl::elems. See ssax:complete-start-tag::preserve-ws?

Faults detected: VC: XML-Spec.html#elementvalid WFC: XML-Spec.html#GIMatch

(ssax:make-parser user-handler-tag    
  user-handler-proc ...)  ???
  user-handler-tag : ???
  user-handler-proc : ???
Create an XML parser, an instance of the XML parsing framework. This will be a SAX, a DOM, or a specialized parser depending on the supplied user-handlers.

user-handler-tag is a symbol that identifies a procedural expression that follows the tag. Given below are tags and signatures of the corresponding procedures. Not all tags have to be specified. If some are omitted, reasonable defaults will apply.

tag: DOCTYPE handler-procedure: PORT DOCNAME SYSTEMID INTERNAL-SUBSET? SEED If internal-subset? is #t, the current position in the port is right after we have read #\[ that begins the internal DTD subset. We must finish reading of this subset before we return (or must call skip-internal-subset if we aren’t interested in reading it). The port at exit must be at the first symbol after the whole DOCTYPE declaration. The handler-procedure must generate four values: ELEMS ENTITIES NAMESPACES SEED See xml-decl::elems for ELEMS. It may be #f to switch off the validation. NAMESPACES will typically contain USER-PREFIXes for selected URI-SYMBs. The default handler-procedure skips the internal subset, if any, and returns (values #f ’() ’() seed)

tag: UNDECL-ROOT handler-procedure: ELEM-GI SEED where ELEM-GI is an UNRES-NAME of the root element. This procedure is called when an XML document under parsing contains _no_ DOCTYPE declaration. The handler-procedure, as a DOCTYPE handler procedure above, must generate four values: ELEMS ENTITIES NAMESPACES SEED The default handler-procedure returns (values #f ’() ’() seed)

tag: DECL-ROOT handler-procedure: ELEM-GI SEED where ELEM-GI is an UNRES-NAME of the root element. This procedure is called when an XML document under parsing does contains the DOCTYPE declaration. The handler-procedure must generate a new SEED (and verify that the name of the root element matches the doctype, if the handler so wishes). The default handler-procedure is the identity function.

tag: NEW-LEVEL-SEED handler-procedure: see ssax:make-elem-parser, my-new-level-seed

tag: FINISH-ELEMENT handler-procedure: see ssax:make-elem-parser, my-finish-element

tag: CHAR-DATA-HANDLER handler-procedure: see ssax:make-elem-parser, my-char-data-handler

tag: PI handler-procedure: see ssax:make-pi-parser The default value is ’()

(ssax:reverse-collect-str LIST-OF-FRAGS)  ???
  LIST-OF-FRAGS : ???
given the list of fragments (some of which are text strings) reverse the list and concatenate adjacent text strings. We can prove from the general case below that if LIST-OF-FRAGS has zero or one element, the result of the procedure is equal? to its argument. This fact justifies the shortcut evaluation below.

6.3 input-parse.ss

(parser-error PORT    
  MESSAGE    
  SPECIALISING-MSG*)  ???
  PORT : port?
  MESSAGE : ???
  SPECIALISING-MSG* : ???
Many procedures of this package call parser-error to report a parsing error. The first argument is a port, which typically points to the offending character or its neighborhood. Most of the Scheme systems let the user query a PORT for the current position. MESSAGE is the description of the error. Other arguments supply more details about the problem.

6.4 sxml-tree-trans.ss

(SRV:send-reply FRAGMENT ...)  ???
  FRAGMENT : ???
Output the ’fragments’ The fragments are a list of strings, characters, numbers, thunks, #f, #t – and other fragments. The function traverses the tree depth-first, writes out strings and characters, executes thunks, and ignores #f and ’(). The function returns #t if anything was written at all; otherwise the result is #f If #t occurs among the fragments, it is not written out but causes the result of SRV:send-reply to be #t

(post-order TREE BINDINGS)  ???
  TREE : ???
  BINDINGS : ???
post-order is a strict subset of pre-post-order without *preorder* (let alone *macro*) traversals. Now pre-post-order is actually faster than the old post-order. The function post-order is deprecated and is aliased below for backward compatibility.

(replace-range:: BEG-PRED END-PRED FOREST)  ???
  BEG-PRED : ???
  END-PRED : ???
  FOREST : ???
Traverse a forest depth-first and cut/replace ranges of nodes.

The nodes that define a range don’t have to have the same immediate parent, don’t have to be on the same level, and the end node of a range doesn’t even have to exist. A replace-range procedure removes nodes from the beginning node of the range up to (but not including) the end node of the range. In addition, the beginning node of the range can be replaced by a node or a list of nodes. The range of nodes is cut while depth-first traversing the forest. If all branches of the node are cut a node is cut as well. The procedure can cut several non-overlapping ranges from a forest.

replace-range:: BEG-PRED x END-PRED x FOREST -> FOREST where type FOREST = (NODE ...) type NODE = Atom | (Name . FOREST) | FOREST

The range of nodes is specified by two predicates, beg-pred and end-pred. beg-pred:: NODE -> #f | FOREST end-pred:: NODE -> #f | FOREST The beg-pred predicate decides on the beginning of the range. The node for which the predicate yields non-#f marks the beginning of the range The non-#f value of the predicate replaces the node. The value can be a list of nodes. The replace-range procedure then traverses the tree and skips all the nodes, until the end-pred yields non-#f. The value of the end-pred replaces the end-range node. The new end node and its brothers will be re-scanned. The predicates are evaluated pre-order. We do not descend into a node that is marked as the beginning of the range.

6.5 sxml-to-html.ss

(SXML->HTML TREE)  ???
  TREE : ???
The following procedure is the most generic transformation of SXML into the corresponding HTML document. The SXML tree is traversed post-oder (depth-first) and transformed into another tree, which, written in a depth-first fashion, results in an HTML document.

(entag TAG ELEMS)  ???
  TAG : symbol?
  ELEMS : (listof sxml?)
Create the HTML markup for tags. This is used in the node handlers for the post-order function, see above.

(enattr ATTR-KEY VALUE)  ???
  ATTR-KEY : ???
  VALUE : ???
Create the HTML markup for attributes. This and entag are being used in the node handlers for the post-order function, see above.

(string->goodHTML STRING)  ???
  STRING : string?
Given a string, check to make sure it does not contain characters such as ’<’ or ’&’ that require encoding. Return either the original string, or a list of string fragments with special characters replaced by appropriate character entities.

6.6 sxml-to-html-ext.ss

(make-header HEAD-PARMS)  ???
  HEAD-PARMS : (listof (list/c symbol? any/c))
Create the ’head’ SXML/HTML tag. HEAD-PARMS is an assoc list of (h-key h-value), where h-value is a typically string; h-key is a symbol: title, description, AuthorAddress, keywords, Date-Revision-yyyymmdd, Date-Creation-yyyymmdd, long-title One of the h-key can be Links. In that case, h-value is a list of (l-key l-href (attr value) ...) where l-key is one of the following: start, contents, prev, next, top, home

(make-navbar: HEAD-PARMS)  ???
  HEAD-PARMS : ???
Create a navigational bar. The argument head-parms is the same as the one passed to make-header. We’re only concerned with the h-value Links

(make-footer HEAD-PARMS)  ???
  HEAD-PARMS : ???
Create a footer. The argument head-parms is the same as passed to make-header.

(universal-conversion-rules)  ???
Bindings for the post-order function, which traverses the SXML tree and converts it to a tree of fragments

The universal transformation from SXML to HTML. The following rules work for every HTML, present and future

(universal-protected-rules)  ???
A variation of universal-conversion-rules which keeps ’<’, ’>’, ’&’ and similar characters intact. The universal-protected-rules are useful when the tree of fragments has to be traversed one more time.

(alist-conv-rules)  ???
The following rules define the identity transformation

7 

7.1 Raw Lists of Exported Identifiers

These lists appear without documentation. Searching this page is probably better than trawling through the source, and perhaps you’ll consider extracting or contributing documentation for them.

7.2 SSAX-code.rkt

  (#%provide
  attlist-fold
  attlist-null?
  attlist-remove-top
  name-compare
  ssax:Prefix-XML
  ssax:S-chars
  ssax:assert-token
  ssax:largest-unres-name
  ssax:skip-pi
  ssax:xml->sxml
  ssax:make-parser
  xml-token-head
  xml-token-kind
  ssax:read-cdata-body
  assq-values
  attlist->alist
  make-empty-attlist
  make-xml-token
  ssax:complete-start-tag
  ssax:handle-parsed-entity
  ssax:read-QName
  ssax:read-attributes
  ssax:read-external-id
  ssax:read-markup-token
  ssax:read-pi-body-as-string
  ssax:skip-S
  ssax:skip-internal-dtd
  ssax:make-parser/positional-args
  ssax:define-labeled-arg-macro
  fold-right
  fold
  string-whitespace?
  attlist-add
  ssax:ncname-starting-char?
  ssax:predefined-parsed-entities
  ssax:read-NCName
  ssax:read-char-data
  ssax:read-char-ref
  run-test
  ssax:resolve-name
  ssax:reverse-collect-str
  ssax:reverse-collect-str-drop-ws
  ssax:scan-Misc
  ssax:uri-string->symbol
  xml-token?
  ssax:make-pi-parser
  ssax:make-elem-parser)

7.3 common.rkt

  (#%provide close-output-string and-let*)

7.4 myenv.rkt

  (#%provide
  cerr
  assert
  cond-expand
  inc
  dec
  ++!
  push!
  assq-def
  nl
  declare
  --
  cout
  identify-error
  myenv:error
  env.bind
  whennot
  assv-def
  assoc-def
  assure
  env.find
  env.demand
  cons*
  let-values*
  ++
  --!)

7.5 util.rkt

  (#%provide
  any?
  make-char-quotator
  list-intersperse
  list-tail-diff
  string-rindex
  string-split
  substring?
  string->integer)

7.6 parse-error.rkt

  (#%provide SSAX:warn parser-error ssax:warn)

7.7 input-parse.rkt

  (#%provide
  skip-until
  assert-curr-char
  input-parse:init-buffer
  next-token
  next-token-of
  skip-while
  define-opt
  peek-next-char)

7.8 look-for-str.rkt

  (#%provide MISCIO:find-string-from-port? find-string-from-port?)

7.9 char-encoding.rkt

  (#%provide
  char-newline
  char-return
  char-space
  ucscode->char
  ascii->char
  char-tab)

7.10 SXML-tree-trans.rkt

  (#%provide SRV:send-reply replace-range foldts post-order pre-post-order)

7.11 sxpathlib.rkt

  (#%provide
  node-or
  node-equal?
  node-join
  sxml:child-elements
  select-kids
  sxml:child-nodes
  sxml:node?
  node-parent
  node-trace
  ntype??
  sxml:child
  node-reverse
  ntype-names??
  sxml:attribute
  take-after
  node-self
  take-until
  as-nodeset
  sxml:complement
  sxml:filter
  nodeset?
  node-closure
  node-pos
  node-reduce
  sxml:parent
  node-eq?
  ntype-namespace-id??
  map-union
  sxml:element?
  sxml:attr-list)

7.12 srfi-12.rkt

  (#%provide
  signal
  condition-property-accessor
  exc:signal
  exn:exception->condition
  make-composite-condition
  make-property-condition
  handle-exceptions
  condition?
  abort
  condition-predicate
  with-exception-handler)

7.13 mime.rkt

  (#%provide MIME:parse-content-type MIME:read-headers http-token-char?)

7.14 http.rkt

  (#%provide
  flush-output-port
  http-transaction
  open-tcp-connection
  shutdown-sender
  define-def)

7.15 access-remote.rkt

  (#%provide
  ar:components->uri
  ar:file-extension
  ar:normalize-dir-lst
  open-input-resource
  ar:path->segments
  ar:resolve-uri-according-base
  ar:resource-type
  ar:segments->path
  ar:uri->components
  resource-exists?)

7.16 id.rkt

  (#%provide
  id:read-document-declaration
  SXML->SXML+id
  id:AttType-ID?
  id:doctype-handler
  id:ending-action
  id:finish-element-handler
  id:ignore-PI
  id:ignore-comment
  id:ignore-until
  id:make-seed
  id:new-level-seed-handler
  id:process-AttlistDecl
  id:process-DefaultDecl
  id:process-ExternalID
  id:process-doctypedecl
  id:process-literal
  id:process-markupdecl*
  id:process-s
  id:read-external-dtd
  id:read-n
  id:read-name
  id:seed-attrs
  id:seed-index
  id:to-small
  id:unite-id-attrs
  id:process-AttDef
  id:process-prolog)

7.17 xlink-parser.rkt

  (#%provide
  xlink:add-default-arc
  xlink:append-branch
  xlink:check-type-show-actuate-constraints
  xlink:construct-xlink-values
  xlink:ending-action
  xlink:finish-element-handler
  xlink:get-port-position
  xlink:make-arc-info
  xlink:make-full-seed
  xlink:namespace-uri
  xlink:new-level-seed-handler
  xlink:read-SXML-attributes
  SXML->SXML+xlink
  SHTML->SHTML+xlink
  xlink:add-arc
  xlink:add-declared-label
  xlink:add-extended
  xlink:add-locator
  xlink:add-resource
  xlink:add-simple
  xlink:all-labels-declared
  xlink:arc-info-data
  xlink:arc-info-from
  xlink:arc-info-linkbase
  xlink:arc-info-position
  xlink:arc-info-to
  xlink:arc-start
  xlink:branch-helper
  xlink:check-helper
  xlink:extended-end
  xlink:extended-start
  xlink:general-end
  xlink:general-start
  xlink:get-uri
  xlink:linkbase-uri
  xlink:locator-end
  xlink:locator-start
  xlink:read-attributes
  xlink:replace-branch
  xlink:resource-data
  xlink:resource-end
  xlink:resource-label
  xlink:resource-start
  xlink:seed-arcs
  xlink:seed-declared-labels
  xlink:seed-locators+resources
  xlink:seed-mode
  xlink:seed-stack
  xlink:seed-sxlink-arcs
  xlink:seed-sxpointer
  xlink:set-uri-for-sxlink-arcs
  xlink:simple-end
  xlink:simple-start
  xlink:sxpointer->childseq
  xlink:sxpointer4sibling
  xlink:values-actuate
  xlink:values-arcrole
  xlink:values-from
  xlink:values-href
  xlink:values-label
  xlink:values-role
  xlink:values-show
  xlink:values-title
  xlink:values-to
  xlink:values-type
  xlink:arc-end
  xlink:make-locator-or-resource
  xlink:make-small-seed
  xlink:none-end
  xlink:none-start
  xlink:parser-error)

7.18 ssax-prim.rkt

  (#%provide reverse-collect-str-drop-ws RES-NAME->SXML reverse-collect-str)

7.19 multi-parser.rkt

  (#%provide
  bad-accessor
  get-sxml-seed
  make-seed
  parent:construct-element
  parent:new-level-seed-handler
  ssax:multi-parser)

7.20 sxml-tools.rkt

  '(#%provide
  sxml:aux-as-list
  sxml:aux-list-node
  sxml:change-attrlist
  sxml:change-name
  sxml:ns-id
  sxml:ns-uri->id
  sxml:shallow-minimized?
  sxml:sxml->xml
  sxml:find-name-separator
  filter-and-map
  sxml:add-aux
  sxml:name
  sxml:node-name
  sxml:node-parent
  sxml:non-terminated-html-tag?
  sxml:ns-list
  sxml:ns-prefix
  sxml:string->xml
  sxml:text
  check-list
  select-first-kid
  sxml:add-attr
  sxml:attr
  sxml:attr->html
  sxml:attr-as-list
  sxml:attr-from-list
  sxml:attr-list-node
  sxml:attr-list-u
  sxml:attr-u
  sxml:aux-list
  sxml:aux-list-u
  sxml:aux-node
  sxml:change-attr
  sxml:change-content
  sxml:content-raw
  sxml:error
  sxml:lookup
  sxml:minimized?
  sxml:name->ns-id
  sxml:normalized?
  sxml:ns-id->nodes
  sxml:ns-id->uri
  sxml:ns-uri
  sxml:num-attr
  sxml:set-attr
  sxml:shallow-normalized?
  sxml:string->html
  sxml:sxml->html
  sxml:element-name
  sxml:empty-element?
  sxml:attr->xml
  sxml:aux-nodes
  sxml:clean
  sxml:content
  sxml:ncname
  sxml:ns-uri->nodes
  sxml:squeeze)

7.21 sxpath-ext.rkt

  '(#%provide
  sxml:merge-sort
  sxml:nested-loop-join
  sxml:not-equal?
  sxml:number
  sxml:preceding
  sxml:string
  sxml:add-string-to-tree
  sxml:boolean
  sxml:id
  sxml:list-head
  sxml:charlst->branch
  sxml:descendant
  sxml:descendant-or-self
  sxml:equality-cmp
  sxml:merge-sort-join
  sxml:namespace
  sxml:preceding-sibling
  sxml:radix-sort-join
  sxml:ancestor
  sxml:ancestor-or-self
  sxml:equal?
  sxml:following
  sxml:following-sibling
  sxml:relational-cmp
  sxml:string->tree
  sxml:string-in-tree?
  sxml:string-value)

7.22 xpath-parser.rkt

  '(#%provide
  sxml:parse-check-sequence
  sxml:assert-end-of-path
  sxml:parse-name
  sxml:skip-ws
  txp:semantic-errs-detected?
  txp:signal-semantic-error
  sxml:whitespace
  txp:error?
  sxml:delimiter
  sxml:non-first?
  sxml:parse-assert
  sxml:parse-check
  sxml:parse-literal
  sxml:parse-natural
  sxml:parse-ncname
  sxml:parse-number
  sxml:parse-qname
  sxml:xpointer-parse-error
  sxml:xpointer-parse-warning
  txp:param-value
  txp:parameterize-parser
  txp:resolve-ns-prefix)

7.23 txpath.rkt

  '(#%provide
  sxml:xpointer+index
  sxml:classic-res
  sxml:core-boolean
  txpath
  sxml:api-helper
  sxml:api-helper0
  sxml:api-index-helper
  sxml:arithmetic-eval
  sxml:classic-params
  sxml:core-ceiling
  sxml:core-concat
  sxml:core-contains
  sxml:core-count
  sxml:core-false
  sxml:core-floor
  sxml:core-id
  sxml:core-lang
  sxml:core-last
  sxml:core-local-name
  sxml:core-name
  sxml:core-namespace-uri
  sxml:core-normalize-space
  sxml:core-not
  sxml:core-number
  sxml:core-position
  sxml:core-round
  sxml:core-starts-with
  sxml:core-string
  sxml:core-string-length
  sxml:core-substring
  sxml:core-substring-after
  sxml:core-substring-before
  sxml:core-sum
  sxml:core-translate
  sxml:core-true
  sxml:xpath
  sxml:xpath+index
  sxml:xpath+root
  sxml:xpath+root+vars
  sxml:xpath-expr
  sxml:xpath-nodeset-filter
  sxml:xpointer
  sxml:xpointer+root+vars
  sxml:xpointer-runtime-error)

7.24 sxpath.rkt

  '(#%provide sxml:id-alist sxpath car-sxpath if-car-sxpath if-sxpath)

7.25 xpath-ast.rkt

  '(#%provide
  txp:ast-params
  txp:ast-api-helper
  txp:ast-operation-helper
  txp:ast-res
  txp:construct-step
  txp:expr->ast
  txp:step-axis
  txp:step-node-test
  txp:step-preds
  txp:step?
  txp:sxpath->ast
  txp:xpath->ast
  txp:xpointer->ast)

7.26 xpath-context_xlink.rkt

  '(#%provide
  draft:ast-function-call
  draft:ast-literal
  draft:ast-node-test
  xlink:get-docs-with-respect-to-loaded
  draft:core-round
  draft:core-substring-after
  xlink:elem-title?
  xlink:get-document-by-uri
  xlink:get-documents-with-params
  draft:ancestor-or-self
  draft:ast-and-expr
  draft:ast-axis-specifier
  draft:ast-equality-expr
  draft:ast-expr
  draft:ast-filter-expr
  draft:core-concat
  draft:core-contains
  draft:core-count
  draft:core-false
  draft:core-floor
  draft:core-id
  draft:reach-root
  draft:smart-make-context
  draft:xpath
  xlink:embed-arcs-into-document
  draft:core-lang
  draft:core-last
  draft:core-local-name
  draft:core-name
  draft:core-namespace-uri
  draft:core-normalize-space
  draft:core-not
  draft:core-number
  draft:core-position
  draft:core-starts-with
  draft:core-string
  draft:na-max
  draft:top?
  sxpath-with-context
  sxpath/c
  xlink:elem-extended?
  xlink:elem-locator?
  xlink:elem-resource?
  xlink:elem-simple?
  xlink:find-doc
  xlink:id-index
  xlink:load-linked-docs-with-params
  xlink:parameterized-load-with-respect-documents
  xlink:parser
  xlink:referenced-linkbase-uris
  draft:ancestor
  draft:api-helper
  draft:arglist->ns+na
  draft:ast-absolute-location-path
  draft:ast-additive-expr
  draft:ast-child-seq
  draft:ast-full-xptr
  draft:ast-function-arguments
  draft:ast-location-path
  draft:ast-multiplicative-expr
  draft:ast-number-list
  draft:ast-or-expr
  draft:ast-path-expr
  draft:ast-predicate
  draft:ast-predicate-list
  draft:ast-relational-expr
  draft:ast-relative-location-path
  draft:ast-step
  draft:ast-step-list
  draft:ast-union-expr
  draft:ast-variable-reference
  draft:ast-xpointer
  draft:attribute
  draft:child
  draft:contextset->nodeset
  draft:core-boolean
  draft:core-ceiling
  draft:core-string-length
  draft:core-substring
  draft:core-substring-before
  draft:core-sum
  draft:core-translate
  draft:core-true
  draft:descendant
  draft:descendant-or-self
  draft:find-proper-context
  draft:following
  draft:following-sibling
  draft:list-head
  draft:list-last
  draft:make-context
  draft:make-list
  draft:na+
  draft:na-min
  draft:na-minus
  draft:na-minus-nneg
  draft:na>
  draft:na>=
  draft:namespace
  draft:parent
  draft:preceding
  draft:preceding-sibling
  draft:recover-contextset
  draft:remove-eq-duplicates
  draft:self
  draft:siblings->context-set
  draft:signal-semantic-error
  draft:sxpath
  draft:xpath-expr
  draft:xpointer
  sxml:context->ancestors
  sxml:context->ancestors-u
  sxml:context->content
  sxml:context->content-u
  sxml:context->node
  sxml:context->node-u
  sxml:context-u?
  sxml:context?
  sxml:document
  txpath-with-context
  txpath/c
  xlink:add-docs-to-vars
  xlink:add-documents-helper
  xlink:add-documents-recursively
  xlink:add-linkbases-recursively
  xlink:api-error
  xlink:arc?
  xlink:arcs-declared-here
  xlink:arcs-embedded
  xlink:arcs-embedded?
  xlink:arcs-linkbase-uris
  xlink:arcs-outgoing
  xlink:arcs-uris
  xlink:axis-arc
  xlink:axis-traverse
  xlink:axis-traverse-arc
  xlink:docs-exchange-arcs
  xlink:docs-variable
  xlink:documents
  xlink:documents-embed
  xlink:elem-arc?
  xlink:get-documents+linkbases
  xlink:node-arcs
  xlink:node-arcs-on-top
  xlink:node-embedded-arcs
  xlink:ntype??
  xlink:referenced-uris
  xlink:remove-equal-duplicates
  xlink:set-uri
  xlink:traverse-arcs
  xlink:unite-duplicate-keys-in-alist
  xlink:uris
  draft:ast-number)

7.27 ddo-axes.rkt

  '(#%provide
  ddo:following-single-level
  ddo:list-last
  ddo:namespace
  ddo:parent
  ddo:parent-pos
  ddo:parent-single-level-pos
  ddo:parent-single-level
  ddo:descendant-pos
  ddo:discard-attributes
  ddo:following
  ddo:preceding-single-level
  ddo:preceding-single-level-pos
  ddo:following-sibling-single-level-pos
  ddo:following-single-level-pos
  ddo:ancestor
  ddo:ancestor-or-self-pos
  ddo:attribute
  ddo:self
  ddo:ancestor-or-self
  ddo:ancestor-pos
  ddo:attr-child
  ddo:attrs-and-values
  ddo:child
  ddo:child-pos
  ddo:descendant
  ddo:descendant-or-self
  ddo:descendant-or-self-pos
  ddo:following-sibling
  ddo:following-sibling-pos
  ddo:following-sibling-single-level
  ddo:preceding
  ddo:preceding-sibling
  ddo:preceding-sibling-pos
  ddo:preceding-sibling-single-level
  ddo:preceding-sibling-single-level-pos)

7.28 ddo-txpath.rkt

  '(#%provide
  ddo:ast-path-expr
  ddo:type-string
  ddo:ast-predicate
  ddo:ast-predicate-list
  ddo:ast-relational-expr
  ddo:construct-pred-values-pos
  ddo:location-step-pos
  ddo:nset-contained?
  ddo:nset-equal?
  ddo:or
  ddo:pos-result-forward?
  ddo:rewrite-step*
  ddo:sxpath
  ddo:txpath
  ddo:type-any
  ddo:ast-function-call
  ddo:ast-literal
  ddo:ast-multiplicative-expr
  ddo:ast-step-list
  ddo:charlst->branch
  ddo:construct-pred-values
  ddo:foldr
  ddo:generate-pred-id
  ddo:get-var-value-from-tree
  ddo:list-head
  ddo:list-ref
  ddo:list-tail
  ddo:location-step-non-intersect
  ddo:ast-location-path
  ddo:check-special-predicate
  ddo:check4ast-number
  ddo:filter-expr-special-predicate
  ddo:get-abs-lpath-value
  ddo:type-number
  ddo:add-var-to-tree
  ddo:add-vector-to-var-binding
  ddo:all-contexts-in-doc
  ddo:api-helper
  ddo:apply-ast-procedure
  ddo:ast-absolute-location-path
  ddo:ast-additive-expr
  ddo:ast-and-expr
  ddo:ast-axis-specifier
  ddo:ast-equality-expr
  ddo:ast-expr
  ddo:ast-filter-expr
  ddo:ast-function-arguments
  ddo:ast-number
  ddo:ast-or-expr
  ddo:ast-relative-location-path
  ddo:ast-step
  ddo:ast-union-expr
  ddo:ast-variable-reference
  ddo:check-ast-desc-os?
  ddo:check-ast-position?
  ddo:filter-expr-general
  ddo:filter-expr-non-pos
  ddo:get-pred-value
  ddo:get-pred-value-pos
  ddo:location-step-non-pos
  ddo:pos-result->nodeset
  ddo:type-boolean
  ddo:type-nodeset
  ddo:unite-2-contextsets
  ddo:unite-multiple-context-sets
  ddo:var-binding->tree
  ddo:vector-copy-set
  ddo:xpath-expr)

7.29 lazy-xpath.rkt

  '(#%provide
  lazy:ast-variable-reference
  lazy:result->list
  lazy:ast-absolute-location-path
  lazy:ast-axis-specifier
  lazy:core-normalize-space
  lazy:core-name
  lazy:core-namespace-uri
  lazy:core-not
  lazy:ancestor
  lazy:ancestor-or-self
  lazy:api-helper
  lazy:ast-additive-expr
  lazy:ast-and-expr
  lazy:ast-equality-expr
  lazy:ast-expr
  lazy:ast-filter-expr
  lazy:ast-function-arguments
  lazy:ast-function-call
  lazy:ast-literal
  lazy:ast-location-path
  lazy:ast-multiplicative-expr
  lazy:ast-number
  lazy:ast-or-expr
  lazy:ast-path-expr
  lazy:ast-predicate
  lazy:ast-predicate-list
  lazy:ast-relational-expr
  lazy:ast-relative-location-path
  lazy:ast-step
  lazy:ast-step-list
  lazy:ast-union-expr
  lazy:attribute
  lazy:axis-consume-nodeset
  lazy:boolean
  lazy:car
  lazy:cdr
  lazy:child
  lazy:contextset->nodeset
  lazy:core-boolean
  lazy:core-ceiling
  lazy:core-concat
  lazy:core-contains
  lazy:core-count
  lazy:core-false
  lazy:core-floor
  lazy:core-id
  lazy:core-lang
  lazy:core-last
  lazy:core-local-name
  lazy:core-number
  lazy:core-position
  lazy:core-round
  lazy:core-starts-with
  lazy:core-string
  lazy:core-string-length
  lazy:core-substring
  lazy:core-substring-after
  lazy:core-substring-before
  lazy:core-sum
  lazy:core-translate
  lazy:core-true
  lazy:descendant
  lazy:descendant-or-self
  lazy:equal?
  lazy:equality-cmp
  lazy:filter
  lazy:find-foll-siblings
  lazy:find-prec-siblings
  lazy:find-proper-context
  lazy:following
  lazy:following-sibling
  lazy:length
  lazy:map
  lazy:namespace
  lazy:node->sxml
  lazy:not-equal?
  lazy:null?
  lazy:number
  lazy:or
  lazy:output-siblings
  lazy:parent
  lazy:preceding
  lazy:preceding-sibling
  lazy:promise?
  lazy:reach-root
  lazy:recover-contextset
  lazy:relational-cmp
  lazy:self
  lazy:string
  lazy:string-value
  lazy:sxpath
  lazy:txpath
  lazy:xpath-expr)

7.30 lazy-ssax.rkt

  '(#%provide
  lazy:except-last
  lazy:force-descendants
  lazy:replace-common
  lazy:seed-common
  lazy:xml->sxml)

7.31 modif.rkt

  '(#%provide
  modif:delete
  modif:delete-undeep
  modif:insert-following
  modif:insert-into
  modif:insert-preceding
  modif:rename
  sxml:assert-proper-attribute
  sxml:clone
  sxml:clone-nset-except
  sxml:lambdas-upd-specifiers->targets
  sxml:modification-error
  sxml:modify
  sxml:separate-list
  sxml:transform-document
  sxml:tree-trans
  sxml:unite-annot-attributes-lists
  sxml:update-specifiers->lambdas)

7.32 serializer.rkt

  '(#%provide
  srl:name->qname-components
  srl:display-fragments-2nesting
  srl:processing-instruction->str-lst
  srl:namespace-assoc-for-elem
  srl:qname->string
  srl:select-kids
  srl:separate-list
  srl:apply-string-append
  srl:assoc-cdr-string=
  srl:atomic->string
  srl:attribute->str-lst
  srl:char-nl
  srl:clean-fragments
  srl:comment->str-lst
  srl:construct-start-end-tags
  srl:conventional-ns-prefixes
  srl:display-node-out-recursive
  srl:display-sxml
  srl:display-top-out
  srl:empty-elem?
  srl:escape-alist-att-value
  srl:escape-alist-char-data
  srl:escape-alist-html-att
  srl:extract-original-prefix-binding
  srl:make-xml-decl
  srl:map-append
  srl:mem-pred
  srl:member-ci
  srl:namespace-decl->str-lst
  srl:newline
  srl:node->nested-str-lst-recursive
  srl:normalize-sequence
  srl:ns-assoc-for-top
  srl:parameterizable
  srl:shtml-entity->char-data
  srl:split-name
  srl:string->att-value
  srl:string->cdata-section
  srl:string->char-data
  srl:string->escaped
  srl:string->html-att
  srl:sxml->html
  srl:sxml->html-noindent
  srl:sxml->string
  srl:sxml->xml
  srl:sxml->xml-noindent
  srl:top->nested-str-lst
  srl:update-space-specifier
  srl:xml-char-escaped)

8 Reporting Bugs

For Heaven’s sake, report lots of bugs!