chickadee » sxml-serializer » allow-prefix-redeclarations?

(allow-prefix-redeclarations? #t) parameter

This parameter determines the default value of the allow-prefix-redeclarations: keyword to serialize-sxml.

If #t, allows redeclaration of XML prefixes when a namespace URI maps to a previously declared XML prefix; if #f, a new prefix will be autogenerated so that XML prefixes map one-to-one to URIs. Defaults to #t. The behavior of the stock sxml-tools serializer is to avoid all prefix redeclarations; to retain this behavior, set this value to #f.

When enabled, you can provide multiple identical prefixes in ns-prefixes, mapped to different URIs. The serializer will redeclare the prefix with a different namespace URI if it has already been declared in a parent:

> (serialize-sxml '((*TOP* (http://foo:one (http://bar:two))
                           (http://bar:three)))
                  ns-prefixes: '((BAZ . "http://foo") (BAZ . "http://bar")))
<BAZ:one xmlns:BAZ="http://foo">
  <BAZ:two xmlns:BAZ="http://bar" />
</BAZ:one>
<BAZ:three xmlns:BAZ="http://bar" />

Contrast this to the case where redeclarations are disallowed:

> (serialize-sxml '((*TOP* (http://foo:one (http://bar:two))
                           (http://bar:three)))
                  ns-prefixes: '((BAZ . "http://foo") (BAZ . "http://bar"))
                  allow-prefix-redeclarations: #f)
<BAZ:one xmlns:BAZ="http://foo">
  <prfx1:two xmlns:prfx1="http://bar" />   <!-- ooooh -->
</BAZ:one>
<BAZ:three xmlns:BAZ="http://bar" />

Here the nested element http://bar:two had its XML prefix prfx1 auto-generated, because BAZ had already been declared in the enclosing scope. Notice that http://bar:three still becomes BAZ:three though, because BAZ was not declared in that element's enclosing scope.

This is extremely useful when the default namespace is employed, because you can declare multiple default namespace URIs, and switch back and forth between the empty namespace and a default namespace. You can consider the default namespace to be a dedicated prefix called *default* which happens to render into XML without a prefix.

(serialize-sxml
  '(*TOP* (http://foo:one
            (http://bar:two
              (http://bar:three)
              (http://foo:four)
              (five (six (http://foo:seven))))))
   ns-prefixes: '((*default* . "http://foo") (*default* . "http://bar")))
<!-- redeclarations #t -->          <!-- redeclarations #f -->
<one xmlns="http://foo">            <one xmlns="http://foo">
  <two xmlns="http://bar">            <prfx1:two xmlns:prfx1="http://bar">
    <three />                           <prfx1:three />
    <four xmlns="http://foo" />         <four />
    <five xmlns="">                     <five xmlns="">
      <six>                               <six>
        <seven xmlns="http://foo" />        <prfx2:seven xmlns:prfx2="http://foo" />
      </six>                              </six>
    </five>                             </five>
  </two>                              </prfx1:two>
</one>                              </one>

One thing to note is that the empty namespace can always be redeclared to be the default namespace, despite the value of allow-prefix-redeclarations?. That's because in XML it is illegal to associate the empty namespace with an XML prefix, so we cannot auto-generate a prefix for it.