Namespace fixup

Manakai Project Note 18 September 2022

This document is no longer maintained. See XML processing and DOM Document Type Definitions specification.

Latest Version
<https://suika.suikawiki.org/www/markup/xml/nsfixup>
Version History
<https://suika.suikawiki.org/gate/git/wi/markup/xmlexts.git/history/HEAD:/nsfixup-source.en.html>
Author
<>

Table of contents

  1. 1 Terminology
  2. 2 Namespace mappings
  3. 3 Namespace fixup of an XML element for serialization
  4. 4 Tests
  5. References

1 Terminology

The terms element (which has namespace, namespace prefix, local name, and attribute list), attribute (which has namespace, namespace prefix, local name, and value), XML namespace, and XMLNS namespace are defined by the DOM Standard [DOM].

2 Namespace mappings

The namespace mapping is a data structure with the following fields:

Default namespace
Either a namespace URL, null, or missing. By default, its value is missing.
Prefix to URL
An ordered list of key/value pairs, where keys are namespace prefixes and values are namespace URLs or none. By default, the set contains two pairs: (xml, the XML namespace) and (xmlns, the XMLNS namespace).

There will be at most one pair with same key in the prefix to URL list. However, there might be more than one pairs with same value in the list.

A default namespace declaration with namespace URL url is an attribute whose namespace is the XMLNS namespace, local name is xmlns, and value is url.

A namespace prefix declaration with prefix prefix and namespace URL url is an attribute whose namespace is the XMLNS namespace, namespace prefix is xmlns, local name is prefix, and value is url.

3 Namespace fixup of an XML element for serialization

The steps for namespace fixup of an XML element for serialization, with an element element and optional namespace mapping nsmap, are as follows:

  1. If nsmap is not specified, let nsmap be a new namespace mapping.
  2. Otherwise, let nsmap be a deep clone of nsmap.
  3. Let attributes be the list containing the attributes in the attribute list of element in same order.
  4. For each attribute attr in attributes, in order:
    1. If the namespace of attr is not the XMLNS namespace, skip the rest of these substeps and continue with any next attribute.
    2. Let local name be the local name of attr.
    3. Let value be the value of attr.
    4. If local name is xml, or if value is the XML namespace or the XMLNS namespace, do nothing.
    5. Otherwise, if local name is xmlns:
      1. If value is the empty string, set the default namespace of nsmap to null.
      2. Otherwise, set the default namespace of nsmap to value.
    6. Otherwise:
      1. Delete the key/value pair whose key is equal to local name, if any, from the prefix to URL list of nsmap.
      2. If value is the empty string, append key/value pair (local name, none) to the prefix to URL list of nsmap.
      3. Otherwise, append key/value pair (local name, value) to the prefix to URL list of nsmap.
  5. Let tag name and new attr be the values returned by the steps to obtain a QName with the namespace, namespace prefix, and local name of element, attributes, and nsmap and with the is element flag.
  6. If new attr is not null, prepend it to attributes.
  7. Let attribute specifications be the empty list.
  8. For each attribute attr in attributes, in order:
    1. Let attr name and new attr be the values returned by the steps to obtain a QName with the namespace, namespace prefix, and local name of attr, attributes, and nsmap (without the is element flag).
    2. If new attr is not null, insert it into attributes just after attr.
    3. Append attribute name/value pair (attr name, the value of attr) to attribute specifications.
  9. Return tag name, attribute specifications, and nsmap.

These steps return three values. The first value, tag name, is used as the tag name in the start and end tag of the serialization of element. The second value, attribute specifications, contains zero or more pairs of attribute names and values, which are used in the start tag of the serialization of element. The third value, nsmap, is used as the input to the steps for serialization of the child elements of element.

The steps to obtain a QName, with parameters namespace URL, prefix, local name, attributes, and nsmap, where attributes and nsmap are shared with the callee such that any modification to them is also reflected to those variables in the steps which invoked these steps, and the is element flag, are as follows:

  1. Let qname be local name.
  2. Let new attr be null.
  3. If namespace URL is null:
    1. If the is element flag is not set, do nothing.
    2. Otherwise, if the default namespace of nsmap is not null:
      1. Set the default namespace of nsmap to null.
      2. If attributes contains an attribute attr whose namespace is the XMLNS namespace and local name is xmlns:
        1. If the value of attr is not the empty string, replace attr in attributes by a new defualt namespace declaration with namespace URL the empty string, preserving the order.
      3. Otherwise, let new attr be a new defualt namespace declaration with namespace URL the empty string.
  4. Otherwise, if namespace URL is not null:
    1. If namespace URL is the XML namespace, let prefix be xml.
    2. Otherwise, if namespace URL is the XMLNS namespace, let prefix be xmlns.
    3. If namespace URL is the XMLNS namespace and qname is xmlns, do nothing.
    4. Otherwise, if the is element flag is set, prefix is null, and the default namespace of nsmap is missing:
      1. Set the default namespace of nsmap to namespace URL.
      2. Let new attr be a new default namespace declaration with namespace URL namespace URL.
    5. Otherwise, if the is element flag is set, prefix is null, and the default namespace of nsmap is equal to namespace URL, do nothing.
    6. Otherwise, if prefix is not null and there is the key/value pair whose key is prefix and value is namespace URL in the prefix to URL list of nsmap, prepend prefix followed by a U+003A COLON character (:) to qname.
    7. Otherwise, if prefix is not null and there is no key/value pair whose key is prefix in the prefix to URL list of nsmap:
      1. Append key/value pair (prefix, namespace URL) to the prefix to URL list of nsmap.
      2. Let new attr be a new namespace prefix declaration with prefix prefix and namespace URL namespace URL.
      3. Prepend prefix followed by a U+003A COLON character (:) to qname.
    8. Otherwise, if there is the key/value pair whose value is equal to namespace URL in the prefix to URL list of nsmap:
      1. Let prefix be the key of the last key/value pair whose value is equal to namespace URL in the prefix to URL list of nsmap.
      2. Prepend prefix followed by a U+003A COLON character (:) to qname.
    9. Otherwise, if the is element flag is set and the default namespace of nsmap is equal to namespace URL, do nothing.
    10. Otherwise, if the is element flag is set, prefix is null, and attribute does not contain an attribute whose namespace is the XMLNS namespace and local name is xmlns:
      1. Set the default namespace of nsmap to namespace URL.
      2. Let new attr be a new default namespace declaration with namespace URL namespace URL.
    11. Otherwise:
      1. Let prefix be an where n is chosen such that n is the minimum non-negative integer an is not found as a key of the prefix to URL list of nsmap.
      2. Append key/value pair (prefix, namespace URL) to the prefix to URL list of nsmap.
      3. Let new attr be a new namespace prefix declaration with prefix prefix and namespace URL namespace URL.
      4. Prepend prefix followed by a U+003A COLON character (:) to qname.
  5. Return qname and new attr.

These steps are based on, but not equivalent to, Gecko's implementation at the time of writing.

These steps do not prevent an unserializable set of tag name and attributes from being returned when, for example, there is an xmlns attribute in null namespace, there is an xml attribute in the XMLNS namespace whose value is not equal to the XML namespace, or the given nsmap contains a key which is not a valid XML NCName.

4 Tests

There is no comprehensive test suite at the time of writing.

There are some tests at: <https://suika.suikawiki.org/~wakaba/test/web/dom/element/inner-html/> and <https://github.com/manakai/perl-web-markup/blob/master/t/modules/Web-XML-Serializer.t>.

References

DOM
DOM Standard, WHATWG.