I can parse XML like this:
import JSDOM from "jsdom";
const myXml = "... some xml loaded from somewhere ...";
const dom = new JSDOM.JSDOM(myXml);
I was really surprised when I googled "jsdom save xml" and I got nothing. I thought JSDOm is one of the most popular libraries for XML manipulation.
In one answer, I've seen this:
window.document.documentElement.outerHTML
That produces garbage code for some reason, for example it converts:
<Node>
<Child attr="attr"/>
<Child attr="attr"/>
<Child attr="attr"/>
<Child attr="attr"/>
</Node>
to
<Node>
<Child attr="attr">
<Child attr="attr">
<Child attr="attr">
<Child attr="attr">
</Child></Child></Child></Child>
</Node>
It also starts the document with:
<html><head></head><body><globe xmlns:xsi="" xmlns:xsd="">
Note that Globe
is the root element of the source XML. It also produces everything in lower-case.
I can parse XML like this:
import JSDOM from "jsdom";
const myXml = "... some xml loaded from somewhere ...";
const dom = new JSDOM.JSDOM(myXml);
I was really surprised when I googled "jsdom save xml" and I got nothing. I thought JSDOm is one of the most popular libraries for XML manipulation.
In one answer, I've seen this:
window.document.documentElement.outerHTML
That produces garbage code for some reason, for example it converts:
<Node>
<Child attr="attr"/>
<Child attr="attr"/>
<Child attr="attr"/>
<Child attr="attr"/>
</Node>
to
<Node>
<Child attr="attr">
<Child attr="attr">
<Child attr="attr">
<Child attr="attr">
</Child></Child></Child></Child>
</Node>
It also starts the document with:
<html><head></head><body><globe xmlns:xsi="http://www.w3/2001/XMLSchema-instance" xmlns:xsd="http://www.w3/2001/XMLSchema">
Note that Globe
is the root element of the source XML. It also produces everything in lower-case.
- You might need to tell JSDOM that it's not parsing HTML. – evolutionxbox Commented Jan 9, 2020 at 17:13
- Yeah, it looks like it interpreted the document as HTML. It wasn't immediately apparent, since the selectors and such worked. – Tomáš Zato Commented Jan 9, 2020 at 17:15
2 Answers
Reset to default 13The method of saving the document was correct. But the method of parsing is wrong. JSDOM
requires HTML and creates an instance of browser DOM. And it must be used as such, so the steps are the same as when parsing XML in browser:
// Create empty DOM, the imput param here is for HTML not XML, and we don want to parse HTML
const dom = new JSDOM.JSDOM("");
// Get DOMParser, same API as in browser
const DOMParser = dom.window.DOMParser;
const parser = new DOMParser;
// Create document by parsing XML
const document = parser.parseFromString(xml, "text/xml");
// save the xml after modifications
const xmlString = document.documentElement.outerHTML;
An alternative (and easy) way to render xml is passing { contentType: "text/xml" } property to JSDOM initializer.
With Content Type:
let testString = `<root><child1/><child2><grandchild>name1</grandchild></child2></root>`
const { JSDOM } = require("jsdom");
const dom = new JSDOM(testString, { contentType: "text/xml"});
const xmlString = dom.window.document.querySelector("root").outerHTML;
console.log(testString);
console.log(xmlString);
outputs:
<root><child1/><child2><grandchild>name1</grandchild></child2></root>
<root><child1/><child2><grandchild>name1</grandchild></child2></root>
But without content type (defaults to text/html):
let testString = `<root><child1/><child2><grandchild>name1</grandchild></child2></root>`
const { JSDOM } = require("jsdom");
const dom = new JSDOM(testString);
const xmlString = dom.window.document.querySelector("root").outerHTML;
console.log(testString);
console.log(xmlString);
renders as:
<root><child1/><child2><grandchild>name1</grandchild></child2></root>
<root><child1><child2><grandchild>name1</grandchild></child2></child1></root>