npm package: @qdabra/build-xml
Description: Helper library for building XML DOMs
Author: James Rishe
Latest version: 0.0.5

# build-xml

Helper library for building XML DOMs

## Example

```js

import { DOMParser } from '@xmldom/xmldom';
import { buildXmlDom, makeElementCreator } from '@qdabra/build-xml';

const parser = new DOMParser();

// use an element creator to create elements in a given namespace
const makeCatElement = makeElementCreator('http://example.qdabra.com/catalog', 'cat');
const makeNoteElement = makeElementCreator('http://example.qdabra.com/notation', 'note');

const makeBook = (title, publishDate) => makeCatElement('Book', {
    attributes: {
        title,
        author,
        publishDate,
    },
});

const doc = buildXmlDom((doc) => 
    // root element
    makeCatElement(doc, 'Catalog', {
        children: [
            // child element
            makeCatElement(doc, 'Books', {
                children: [
                    makeBook(doc, 'The Great Gatsby', 'F. Scott Fitzgerald', '1925'),
                    makeBook(doc, 'Où es-tu', 'Marc Levy', '2001'),
                    makeBook(doc, '君の名は。', '新海誠', '1996'),
                ],
            }),
            makeNoteElement(doc, 'Comment', {
                text: 'Last updated: 2023-08-25',
            }),
        ],
        // namespace declarations
        namespaces: {
            'cat': 'http://example.qdabra.com/catalog',
            'note': 'http://example.qdabra.com/notation',
        },
    }),
    // pass any DOM compliant parser here
    // can be omitted in browsers
    { parser },
);


```

## Result

```xml

<cat:Catalog xmlns:cat="http://example.qdabra.com/catalog" xmlns:note="http://example.qdabra.com/notation">
  <cat:Books>
    <cat:Book title="The Great Gatsby" author="F. Scott Fitzgerald" publishDate="1925"/>
    <cat:Book title="Où es-tu" author="Marc Levy" publishDate="2001"/>
    <cat:Book title="君の名は。" author="新海誠" publishDate="1996"/>
  </cat:Books>
  <note:Comment>Last updated: 2023-08-25</note:Comment>
</cat:Catalog>

```

## Functions

### buildXmlDom

```js
buildXmlDom(
    buildRoot: (DOMDocument) -> Element | Node[],
    options?: BuildDomOptions,
) -> DOMDocument
```

Builds an XML DOM using the provided root creation function.

The provided function should either return a single DOMElement or an array of nodes including one DOMElement and other non-element nodes that are permitted at the root of an XML document (comments, processing instructions, etc.)

The element returned from the `buildRoot` function can contain further child nodes, etc., essentially representing an entire node tree, and this is the intended way to use this function.

This function will use the `DOMParser` provided in `options` to create the DOM document. If none is provided, it will attempt to create one with `window.DOMParser`.

**Returns** A DOM document containing the returned node(s)

### Example:

```js
const childNames = ['a', 'b', 'c'];

const makeChild = (dom) => (name) => createElement(
    dom,
    null,
    name,
);

/*
    <myDocument>
        <a />
        <b />
        <c />
    </myDocument>
*/
const myDocument = buildXmlDom(
    (dom) => createElement(
        dom,
        null,
        'myDocument',
        {
            children: childNames.map(makeChild(dom)),
        },
    ),
);
```

<hr />

### createElement

```js
createElement(
    dom: DOMDocument,
    namespaceURI: string,
    qualifiedName: string,
    options? CreateElementOptions,
) -> DOMElement
```

Creates a single DOM element with the specified namespace and name.

For elements that are not in a namespace, specify `null` for the `namespaceURI`.

If the name includes a prefix, include the prefix in the value specified for `qualifiedName`.

See below for more details about `CreateElementOptions`.

**Returns:** the created element

### Example:

```js
const NS_XSL = 'http://www.w3.org/1999/XSL/Transform';

/*
    <xsl:template name="MyTemplate" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:text>Some Text</xsl:text>
    </xsl:template>
*/
const xslTemplateElement = createElement(
    dom,
    NS_XSL,
    'xsl:template',
    {
        attributes: {
            name: 'MyTemplate',
        },
        children: [
            createElement(
                dom,
                NS_XSL,
                'xsl:text',
                {
                    text: 'Some Text',
                },
            ),
        ],
    },
);
```

<hr />

### makeElementCreator

```js
makeElementCreator(
    namespaceURI?: string,
    prefix?: string,
) -> ElementCreator
```

Creates a function which is similar to `createElement`, but which allows omitting the namespace URI and prefix. Useful when you want to create different elements in the same namespace.

You can omit both arguments to make an element creator for elements with no namespace.

**Returns:** an element creation function

### Example

```js
const makeXslElement = makeElementCreator(
    'http://www.w3.org/1999/XSL/Transform',
    'xsl',
);

/*
    <xsl:template name="MyTemplate" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:text>Some Text</xsl:text>
    </xsl:template>
*/
const xslTemplateElement = makeXslElement(
    dom,
    'template',
    {
        attributes: {
            name: 'MyTemplate',
        },
        children: [
            makeXslElement(
                'text',
                {
                    text: 'Some Text',
                },
            ),
        ],
    },
);
```

<hr />

### makeEmptyDom

```js
makeEmptyDom(
    parser?: DOMParser,
) -> DOMDocument
```

Creates a new DOMDocument with no nodes, using the given parser.

If no parser is given, will attempt to create one with `window.DOMParser`.

**Returns:** The created DOM document

### Example:

```js
const myDom = makeEmptyDom();
```

<hr />

### makeProcessingInstruction

```js
makeProcessingInstruction(
    dom: DOMDocument,
    name: string,
    attributes: Record<string, string>,
) -> DOMProcessingInstruction
```

Creates a new processing instruction with the provided pseudo-attributes.

**Returns:** The created processing instruction

### Example:

```js
/*
    <?Book title="Love means never having to say &quot;I&apos;m sorry&quot;" author="John Doe"?>
*/
const myPi = makeProcessingInstruction(
    dom,
    'Book',
    {
        title: `Love means never having to say "I\'m sorry"`,
        author: "John Doe",
    },
);
```

<br />

### parseXmlString

```js
parseXmlString(
    xmlString: string,
    parser?: DOMParser,
) -> DOMDocument
```

Parses the specified XML string into an XML document.

If no parser is given, will attempt to create one with `window.DOMParser`.

**Returns:** the parsed document

### Example: 

```js
const myDoc = parseXmlString('<Books><Book>Lord of the Rings</Book><Book>The Prince and the Pauper</Book></Books>');
```

## Interfaces

### CreateElementOptions

```ts
{
    children?: Node[];
    attributes?: Record<string, string>;
    text?: string;
    namespaces?: Record<string, string>;
    nsAttributes?: Record<string, Record<string, string>>;
}
```

Passed to `createElement()` or to element creators created using `makeElementCreator`.

`children` - array of children to append to the created element

`attributes` - a set of key-value pairs for the names and values of non-namespace attributes to add to the element

`text` - text content to add within the element. Any child nodes specified in `children` will be appended after the given text.

`namespaces` - a set of key value pairs for namespace prefixes and namespace URIs, to be added as namespace declarations on the element

`nsAttributes` - key value pairs where the keys are namespace URIs, and the values are key-value collections of attribute names and values.

Example:

```js
const NS_XSI = "http://www.w3.org/2001/XMLSchema-instance";
const NS_XSD = "http://www.w3.org/2001/XMLSchema";

{
    [NS_XSI]: {
        'xsi:schemaLocation': './myschema.xsd',
        'xsi:nil': 'true',
    },
    [NS_XSD]: {
        'xsd:type': 'xsd:string',
    },
}
```

<hr />

### BuildDomOptions

```ts
{
    parser?: DOMParser;
}
```

Passed to `buildXmlDom` to indicate a parser to use when creating the DOM.

<hr />

### ElementCreator

```js
(
    dom: Document,
    localName: string,
    options?: CreateElementOptions,
) -> Element;
```

The signature of functions created with `makeElementCreator()`.

This is similar to the signature of `makeElement()`, but does not have a `namespaceURI` parameter, and has a `localName` parameter instead of a `qualifiedName` parameter.