XML to JavaScript Object

XMLHttpRequest(XHR)があるのだからブラウザでXML扱えないわけないんだけど、今時JSONのほうが圧倒的に多いので存在を忘れる。fetchが全ブラウザで使えるようになって久しいからxhrもなかなか見ないしね。

DOMParserを使えばXMLをパース出来る。

XML のパースとシリアライズ - XML: Extensible Markup Language | MDN


パースした後はDOMツリーになるから、基本DOMのまま扱えばいいじゃん派だけど、querySelectorつか使えるわけだし、でもReactなりVueなりで扱うときにはプレーンなオブジェクトになってた方が圧倒的に楽じゃんという意見はその通りだと思う。

きれいに構造化されてなくていいから、とりあえず、プレーンなオブジェクトに変換してみる。

※ きれいじゃないってのは、["hoge", "fuga"]みたいな構造にはならず、[{$text:"hoge"}, {"fuga"}]みたいなオブジェクトでラップされたものになるということ。

const xmlStr = '<q id="a"><span id="b">hey!</span></q>';
const parser = new DOMParser();
const doc = parser.parseFromString(xmlStr, "application/xml");

function toObject(el) {
  const o = {};
  o.$type = el.nodeName;
  for (let a of el.attributes) {
    o[a.name] = a.value;
  }
  const $text = 
    Array.from(el.childNodes)
      .filter(n => n.nodeType === Node.TEXT_NODE)
      .map(n => n.nodeValue ?? '')
  if ($text.length > 0) {
    o.$text = $text.join('')
  }

  if (el.children.length > 0) {
    o.$children = Array.from(el.children).map(toObject);
  }

  return o;
}

const obj = toObject(doc.firstChild)
console.log(JSON.stringify(obj, null, '\t'))

/*
{
	"$type": "q",
	"id": "a",
	"$children": [
		{
			"$type": "span",
			"id": "b",
			"$text": "hey!"
		}
	]
}
*/