Skip to content

Instantly share code, notes, and snippets.

@teramako
Created September 12, 2012 12:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teramako/3706243 to your computer and use it in GitHub Desktop.
Save teramako/3706243 to your computer and use it in GitHub Desktop.
ObjectをDOM変換する
/*
* @example
* var tree = {
* body: [
* {$: "p",
* attrs: { "liberator:highlight": "Hint", },
* child: "hoge",
* },
* "text node",
* {$: "p",
* attrs: { class: "foo" },
* child: {
* b: "foo"
* }
* }
* ]
* };
* document.appendChild(
* JSXML.toDOM(tree, document, { liberator: "http://vimperator.org/namespaces/liberator" })
* );
*/
const EXPORTED_SYMBOLS = ["JSXML"];
const JSXML = (function(){
function getNS (name, aNS) {
var pos = name.indexOf(":");
if (pos === -1)
return null;
var prefix = name.substr(0, pos);
return aNS[prefix] || null;
}
function toObject (aElement) {
var container;
if (aElement.nodeType === Node.ELEMENT_NODE) {
container = {
$: (aElement.prefix ? aElement.prefix + ":" : "") + aElement.localName
};
if (aElement.attributes.length > 0) {
container.attrs = {};
for (let i = 0, len = aElement.attributes.length; i < len; ++i) {
let attr = aElement.attributes[i];
let attrName = (attr.prefix ? attr.prefix + ":" : "") + attr.localName;
container.attrs[attrName] = attr.value;
}
}
if (aElement.hasChildNodes()) {
container.child = [];
for (let i = 0, len = aElement.childNodes.length; i < len; ++i) {
let node = aElement.childNodes[i];
container.child.push(node.nodeType === Node.TEXT_NODE ? node.data : toObject(node));
}
}
} else if (aElement.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
container = [];
for (let i = 0, len = aElement.childNodes.length; i < len; ++i) {
let node = aElement.childNodes[i];
container.push(node.nodeType === Node.TEXT_NODE ? node.data : toObject(node));
}
}
return container;
}
/** toDOM {{{2
* @param {Object} aObj
* @param {Element|DocumentFragment} aParent
* @param {Document} aDoc
* @param {Object} aNS
* @return {Element|DocumentFragment} return aParent
*/
function toDOM (aObj, aParent, aDoc, aNS) {
if (aObj == null)
aObj = String(aObj);
switch (typeof aObj) {
case "string":
case "number":
case "boolean":
aParent.appendChild(aDoc.createTextNode(aObj.toString()));
break;
case "object":
if (Array.isArray(aObj)) {
for (let i = 0, len = aObj.length; i < len; ++i) {
toDOM(aObj[i], aParent, aDoc, aNS);
}
} else if ("$" in aObj) {
let ns = getNS(aObj.$, aNS);
let child = ns ? aDoc.createElementNS(ns, aObj.$) : aDoc.createElement(aObj.$);
if ("attrs" in aObj) {
for (let attr in aObj.attrs) {
child.setAttributeNS(getNS(attr, aNS), attr, aObj.attrs[attr]);
}
}
if ("child" in aObj)
toDOM(aObj.child, child, aDoc, aNS);
aParent.appendChild(child);
} else {
for (let key in aObj) {
if (key.charAt(0) === "@") {
let attrName = key.substr(1);
aParent.setAttributeNS(getNS(attrName, aNS), attrName, aObj[key]);
} else if (key === "text") {
aParent.appendChild(aDoc.createTextNode(aObj.text));
} else {
let ns = getNS(key, aNS);
let child = ns ? aDoc.createElementNS(ns, key) : aDoc.createElement(key);
aParent.appendChild(toDOM(aObj[key], child, aDoc, aNS));
}
}
}
}
return aParent;
} // 2}}}
return {
toDOM: function JSXML_toDOM (aTree, aDoc, aNS) {
if (!aNS)
aNS = {};
return toDOM(aTree, aDoc.createDocumentFragment(), aDoc, aNS);
},
toObject: function JSXML_toObject (aElement) {
return toObject(aElement);
}
};
}());
//vim :set fdm=marker sw=2 ts=2:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment