将html内容分解为单独的更高级别的html标记并将它们存储在数组中

时间:2016-02-15 13:50:42

标签: javascript html reactjs redux

我正在试图弄清楚如何实现以下目标。

假设我有字符串,就像这样

"<h1>My heading</h1> <p><ul><li>Some item</li></ul> Some paragraph text</p> <p>Another paragraph text in <b>bold</b></p>"

我需要将此字符串拆分为更高级别的标记并将它们放入数组中,例如:

[
  "<h1>My heading</h1>",
  "<p><ul><li>Some item</li></ul> Some paragraph text</p>",
  "<p>Another paragraph text in <b>bold</b></p>"
]

注意嵌套标签是如何分开的。此外,我永远不知道哪个标签可以在更高级别上,因此在这种情况下,除了h1p之外,还有其他任何标签。

2 个答案:

答案 0 :(得分:0)

您可以将字符串转换为DOM元素,循环和拆分,然后重新转换为字符串(不确定它是否是最佳方式):

var str = "<h1>My heading</h1> <div><ul><li>Some item</li></ul> Some paragraph text</div> <p>Another paragraph text in <b>bold</b></p>";

var arr = [];
var dom = document.createElement('div');

// Convert your string
dom.innerHTML = str;

// Loop through the dom structure and push only direct children into the array
for (var key in dom.childNodes) {
    if (dom.childNodes[key].nodeType !== 3 && dom.childNodes[key].parentElement === dom) {
      arr.push(dom.childNodes[key]);
    }
}

// Traverse the array and re-convert the dom elements into strings
arr = arr.map(function(el){
  var wrap = document.createElement('div');
  wrap.appendChild(el);
  return wrap.innerHTML;
});

console.log(arr);

注意:您的确切示例不会起作用,因为您在html中的p元素中不能有ul元素。

答案 1 :(得分:0)

您可以执行以下操作以避免使用jQuery或DOM元素。

htmlToPhrases('hello <p>my name is <span>Roman</span></p><span>!</span>');

它会返回

[
    "hello ",
    "<p>my name is <span>Roman</span></p>",
    "<span>!</span>"
]

<强>代码

function htmlToPhrases(text) {
    let acc = [];
    while (text) {
        if (text[0] !== '<') {
            const nextOpenTag = text.indexOf('<');
            if (nextOpenTag === -1) {
                acc.push(text);
            } else {
                acc.push(text.substr(0, nextOpenTag));
            }
        } else {
            acc.push(_getFirstTag(text));
        }
        text = text.substr(acc[acc.length - 1].length);
    }
    return acc;
}

function _getFirstTag(text, acc = '', level = 0) {
    const afterOpenChar = text.indexOf('<') + 1;
    const nextTag = text[afterOpenChar];

    level += nextTag === '/' ? -1 : 1;

    acc += text.substr(0, afterOpenChar);
    text = text.substr(afterOpenChar);

    if (level === 0) return acc + text.substr(0, text.indexOf('>') + 1);

    return _getFirstTag(text, acc, level);
}