Some XML helpers to help with OOXML development
[!NOTE]
These are all based around xml-js and output that modules internal format
API
asXmlElement
When working with xml-js it's really handy to not have to worry about when you're passing an XML string our the xml-js JSON type called Element
This helper function just outputs an Element for either input
asXmlElement ("<name>foo</name>" );
asXmlElement ({ name : "name" , text : "foo" });
[!NOTE]
All the other functions in this document that accept XML, also accept this Element (using this function)
safeXml
An XML tagged template literal with the following features
error if XML is incorrect
array support in substitution
The following will error in development, because of mismatched start/end tags
safeXml`<foo>hello</bar>` ;
Substitution of arrays "just works" so you can map values in the tagged template literals
const items = [1 , 2 , 3 ].map ((n ) => safeXml`<name>item ${1 } </name>` );
const outXml = safeXml`<test>${items} </test>` ;
assert.equal (
outXml,
`<test><name>item 1</name><name>item 2</name><name>item 3</name></test>` ,
);
This also makes it easy to support https://prettier.io/docs/en/options#embedded-language-formatting
compact
Removes non required whitespace from the XML
const outXml = compact (`
<test>
something
</test>
` );
assert.equal (outXml, "<test>something</test>" );
collapseFragments
For XML to be valid, there must be a single root node. When composing apps it's handy for that not to be true.
For example the following would error
const xml = safeXml`
<name>foo</name>
<name>bar</name>
` ;
So instead we'd like something like a HTML fragment
const xml = safeXml`
<XML_FRAGMENT>
<name>foo</name>
<name>bar</name>
</XML_FRAGMENT>
` ;
So we did just that, collapseFragments walks over a tree removing <XML_FRAGMENT>...</XML_FRAGMENT> nodes.
const innerBit = safeXml`
<XML_FRAGMENT>
<name>foo</name>
<name>bar</name>
</XML_FRAGMENT>
` ;
const newXml = collapseFragments (
safeXml`
<doc>
${innerBit}
</doc>
` ,
);
assert.equal (
newXml,
`
<doc>
<name>foo</name>
<name>bar</name>
</doc>
` ,
);
cdata
From the wikipedia page
CDATA section is a piece of element content that is marked up to be interpreted literally, as textual data, not as marked-up content.
But <name><![CDATA[one < two]]><name> is ugly and hard to read, so instead
safeXml`<name>${cdata("one < two" )} </name>` ;
format
Format XML in a consistent way, useful for logging and snapshot testing
format (`
<test> one
</test>
` );
getAllByTestId
const element = getAllByTestId (`
<root>
<name _testid="test">
Hello
</name>
</test>
` )
getByTestId
const element = getByTestId (`
<root>
<name _testid="test">
Hello
</name>
</test>
` )
getSingleTextNode
Returns a single text node if one exists
getSingleTextNode (`<test>hello world</test>` )
Else throws an error
getSingleTextNode (`<test>hello <foo>inner node</foo> world</test>` )
removeTestIds
const element = removeTestIds (`
<root>
<name _testid="test">
Hello
</name>
</test>
` )
CI
License
MIT