将标记解析为对象树并将其转换为MXML可能更容易。
事情是这样的:
var source_code = $("body").html();
var openStartTagRx = /^\s*
var closeStartTagRx = /^\s*>/i;
var closeTagRx = /^\s*/i;
var attrsRx = new RegExp(
'^\\s+' +
'(?:(data-type)|([a-z-]+))' + // group 1 is "data-type" group 2 is any attribute
'\\=' +
'(?:\'|")' +
'(.*?)' + // group 3 is the data-type or attribute value
'(?:\'|")',
'mi');
function Thing() {
this.type = undefined;
this.attrs = undefined;
this.children = undefined;
}
Thing.prototype.addAttr = function(key, value) {
this.attrs = this.attrs || {};
this.attrs[key] = value;
};
Thing.prototype.addChild = function(child) {
this.children = this.children || [];
this.children.push(child);
};
function getErrMsg(expected, str) {
return 'Malformed source, expected: ' + expected + '\n"' + str.slice(0,20) + '"';
}
function parseElm(str) {
var result,
elm,
childResult;
if (!openStartTagRx.test(str)) {
return;
}
elm = new Thing();
str = str.replace(openStartTagRx, '');
// parse attributes
result = attrsRx.exec(str);
while (result) {
if (result[1]) {
elm.type = result[3];
} else {
elm.addAttr(result[2], result[3]);
}
str = str.replace(attrsRx, '');
result = attrsRx.exec(str);
}
// close off that tag
if (!closeStartTagRx.test(str)) {
throw new Error(getErrMsg('end of opening tag', str));
}
str = str.replace(closeStartTagRx, '');
// if it has child tags
childResult = parseElm(str);
while (childResult) {
str = childResult.str;
elm.addChild(childResult.elm);
childResult = parseElm(str);
}
// the tag should have a closing tag
if (!closeTagRx.test(str)) {
throw new Error(getErrMsg('closing tag for the element', str));
}
str = str.replace(closeTagRx, '');
return {
str: str,
elm: elm
};
}
console.log(parseElm(source_code).elm);
这将解析为以下提供的标记:
{
"type" : "Application"
"attrs" : { "id" : "app" },
"children" : [
{ "type" : "Label" },
{ "type" : "Button" },
{ "type" : "VBox" },
{ "type" : "Group" }
],
}
这是递归的,所以嵌入式组解析了。