JavaScript正则表达式:去除未闭合的标签

3
我正在寻找JavaScript正则表达式解决方案,以删除未闭合的标签,例如:
<div></div><span>

您可以看到,我想要删除<span>元素。我知道在标记上使用正则表达式是一个不好的做法,但这对我的项目是必需的。这是我制作的正则表达式模式,但它没有起作用:

/<([a-z]+?)>([\s\S]*?)(?!<\/\1>)/g

我正在使用JavaScript replace函数将所有匹配项替换为“”,我的模式旨在匹配未关闭的标签,有关该模式的内容:

  1. [a-z]我知道HTML标记可以包含=,",etc,所以我正在寻找一个简单的模式,以便我可以进行编辑,因此我从[a-z]开始。
  2. 我使用了!?来拒绝关闭标记的匹配。

我知道我的模式不起作用,如果有人有想法,我将非常感激。

编辑:

我知道可能存在递归,如果这是情况,我希望删除所有递归树,我只想保留1个级别的HTML,例如:

<div><span></span></div><p></p>

如果 <div> 标签后面不是 </div>,则将其删除。

说真的,在Javascript中使用完整的正则表达式解决这个问题是不可能的,因为Javascript的正则表达式没有递归功能(除了在.net中使用堆栈系统处理嵌套标签的方法)。 - Casimir et Hippolyte
所以,我只是想确保我理解了,<div><span></span></div><p></p>,这是完全有效的HTML代码,你要把它变成<div></div><p></p> - dtyler
是的,我想保留1级HTML。 - Aviel Fedida
https://dev59.com/X3I-5IYBdhLWcg3wq6do#1732454 - Stephen P
我使用了这段HTML解析器脚本来清理用户输入的所见即所得标记。它对我的目的非常有效,但只处理HTML4标记。John的脚本中的正则表达式可能对其他希望进行一些Javascript DOM解析的人有所帮助。http://ejohn.org/apps/htmlparser/ - Dylan Valade
1个回答

5

首先,让我们看一下OP说了什么:

  • 我知道在标记上使用正则表达式是一个坏主意,但这是我的项目所必需的。
  • 我只想保留1级html

这是可以实现的。

你已经走在了正确的轨道上。然而,你不应该使用!?来拒绝匹配闭合标签。你想要接受它们。这样匹配就不会接受未关闭的标签,这正是我们的目标。

现在,你的正则表达式将是这样的。

/<([a-z]+?)>([\s\S]*?)(<\/\1>)/g

我们可以移除第二个和第三个括号,因为它们并不必要。
/<([a-z]+?)>[\s\S]*?<\/\1>/g

如果我们在提供的代码上测试这个正则表达式,将会得到以下结果:
"<div><span></span></div><p></p>".match(/<([a-z]+?)>[\s\S]*?<\/\1>/g)
["<div><span></span></div>", "<p></p>"]

看起来我们的正则表达式匹配了太多的符号。我们必须在"<"符号处中断匹配,因为它表示新标签。"[^<]" 表示“除了"<"之外的任何字符”。

"<div><span></span></div><p></p>".match(/<([a-z]+?)>[^<]*?<\/\1>/g)
["<span></span>", "<p></p>"]

最后,我们只需要将匹配结果连接起来即可。
"<div><span></span></div><p></p>".match(/<([a-z]+?)>[^<]*?<\/\1>/g).join("")
"<span></span><p></p>"

哇喔,正则表达式的第一部分就交给你了,因为它不是问题的一部分。希望这对你有所帮助。如果您有进一步的问题,我很乐意回答。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接