Skip to content

Commit

Permalink
Rework prefix resolution during serialization
Browse files Browse the repository at this point in the history
This re-implements the algorithms used to determine what prefixes to
assign and what declarations to output for them during serialization.
The algorithms in the DOM parsing and serialization spec contain too
many bugs that have so far not been addressed, and contain complicated
branching that makes it hard to reason about them.

In the replacement I've tried to remain close to the original behavior
in spirit. That is, existing prefixes (or, for elements, an inherited
default namespace) are preferred over authored prefixes but only if they
are still in scope. Authored prefixes are preferred over generated ones.
A new prefix is generated only if the authored prefix of an attribute
conflicts with a declaration on the same element. Declaration attributes
in the DOM are only preserved if they actually represent a change to the
namespaces in scope for their element and do not cause conflicts - the
spec preserved default namespace declarations in a few other cases but
those seemed unnecessary.
  • Loading branch information
bwrrp committed Oct 19, 2023
1 parent 2a87390 commit eb6c891
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 609 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"jest.jestCommandLine": "npm run test --"
}
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Fast, tiny, standards-compliant XML DOM implementation for node and the browser.
This is a (partial) implementation of the following specifications:

- [DOM living standard][domstandard], as last updated 19 December 2021
- [DOM Parsing and Serialization W3C Editor's Draft][domparsing], as last updated 20 April 2020
- [DOM Parsing and Serialization W3C Editor's Draft][domparsing], as last updated 2 May 2021
- [Extensible Markup Language (XML) 1.0 (Fifth Edition)][xmlstandard]
- [Namespaces in XML 1.0 (Third Edition)][xml-names]

Expand Down Expand Up @@ -37,24 +37,24 @@ The package includes both a commonJS-compatible UMD bundle (`dist/slimdom.umd.js

## Usage

Create documents using the slimdom.Document constructor, and manipulate them using the [standard DOM API][domstandard].
Create documents by parsing XML or start from scratch using the slimdom.Document constructor, and manipulate them using the [standard DOM API][domstandard].

```javascript
import * as slimdom from 'slimdom';
// alternatively, in node and other commonJS environments:
// const slimdom = require('slimdom');

// Start with an empty document:
const document = new slimdom.Document();
document.appendChild(document.createElementNS('http://www.example.com', 'root'));
const xml = slimdom.serializeToWellFormedString(document);
// -> '<root xmlns="http://www.example.com"/>'

// Or parse from a string:
// Parse from a string:
const document2 = slimdom.parseXmlDocument('<root attr="value">Hello!</root>');
document2.documentElement.setAttribute('attr', 'new value');
const xml2 = slimdom.serializeToWellFormedString(document2);
// -> '<root attr="new value">Hello!</root>'

// Or start with an empty document:
const document = new slimdom.Document();
document.appendChild(document.createElementNS('http://www.example.com', 'root'));
const xml = slimdom.serializeToWellFormedString(document);
// -> '<root xmlns="http://www.example.com"/>'
```

Some DOM API's, such as the `DocumentFragment` constructor, require the presence of a global document, for instance to set their initial `ownerDocument` property. In these cases, slimdom will use the instance exposed through `slimdom.document`. Although you could mutate this document, it is recommended to always create your own documents (using the `Document` constructor) to avoid conflicts with other code using slimdom in your application.
Expand All @@ -71,11 +71,11 @@ This library implements:
- `XMLSerializer`, and read-only versions of `innerHTML` / `outerHTML` on `Element`.
- `DOMParser`, for XML parsing only.

This library is currently aimed at providing a lightweight and consistent experience for dealing with XML and XML-like data. For simplicity and efficiency, this implementation deviates from the spec in a few minor ways. Most notably, normal JavaScript arrays are used instead of `HTMLCollection` / `NodeList` and `NamedNodeMap`, HTML documents are treated no different from other documents and a number of features from in the DOM spec are missing. In most cases, this is because alternatives are available that can be used together with slimdom with minimal effort.
This library is aimed at providing a lightweight and consistent experience for dealing with XML and XML-like data. For simplicity and efficiency, this implementation deviates from the spec in a few minor ways. Most notably, normal JavaScript arrays are used instead of `HTMLCollection` / `NodeList` and `NamedNodeMap`, HTML documents are treated no different from other documents and a number of features from in the DOM spec are missing. In most cases, this is because alternatives are available that can be used together with slimdom with minimal effort.

Do not rely on the behavior or presence of any methods and properties not specified in the DOM standard. For example, do not use JavaScript array methods exposed on properties that should expose a NodeList and do not use Element as a constructor. This behavior is _not_ considered public API and may change without warning in a future release.

This library implements the changes from [whatwg/dom#819][dom-adopt-pr], as the specification as currently described has known bugs around adoption.
This library implements the changes from [whatwg/dom#819][dom-adopt-pr], as the DOM specification as currently described has known bugs around adoption. It also deviates from the [DOM serialization algorithms][domparsing] that deal with assigning and resolving conflicts in namespace prefixes, as the specification has a number of bugs that currently remain unaddressed.

As serializing XML using the `XMLSerializer` does not enforce well-formedness, you may instead want to use the `serializeToWellFormedString` function which does perform such checks.

Expand Down
2 changes: 1 addition & 1 deletion api/slimdom.api.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"metadata": {
"toolPackage": "@microsoft/api-extractor",
"toolVersion": "7.35.1",
"toolVersion": "7.38.0",
"schemaVersion": 1011,
"oldestForwardsCompatibleVersion": 1001,
"tsdocConfig": {
Expand Down
Loading

0 comments on commit eb6c891

Please sign in to comment.