使用正则表达式在HTML中查找列表的开头

时间:2009-05-06 22:15:18

标签: regex

我在网页中有一个TextBox,我正在使用javascript来解析和修改HTML格式。 90%的效果非常好,我试图支持的最后一个主要功能是从word文档中复制和粘贴。我完全得到了它,我只是坚持寻找列表并将它们包装在UL标签中。

因此,使用正则表达式,我想在此文本中找到列表:

<p>paragraph goes here

<li>goes here<br/>
<li>list item 2<br/>
<li>list item 3<br/>

<p>another paragraph

并使用<li>标记包装<ul>部分。我的正则表达不是那么好,有人可以帮忙吗?

-----更新-----

虽然我很感谢所有反馈,基本上表明我需要从头开始解决这个问题,但我没有时间这样做。我完全理解正则表达式不是处理HTML格式的理想方式,但我现在如何使用它,它将处理我的用户希望做的大部分工作。我只需要HTML标签的子集,而不是完整的HTML编辑器。

我的内容来源是用户从word文档(约99.9%)复制和粘贴的时间。我使用正则表达式将HTML标记插入纯文本。对于列表,我发现子弹字符MS word插入其复制的文本中,并用<LI>标记替换它。我只是想让<LI>标签包裹<UL>标签更加用户友好。

我会考虑能够正确地结束我的标签,所以..假设它们已正确结束,用<ul>标签包装我的列表项的正则表达式是什么?

谢谢!

4 个答案:

答案 0 :(得分:7)

  

有些人在面对问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。 - 杰米·扎温斯基

  1. 正则表达式和HTML特别不合适。

  2. 这是2009年,在HTML中使用结束标记。 (如果你真的希望正确使用你的html,那将对你有所帮助。

  3. 如果您已在浏览器中使用此页面,请使用DOM!让浏览器为您解析HTML(如果必须,将其推送到隐藏的div中)并导航生成的DOM树。

答案 1 :(得分:5)

Don't parse HTML with regexesInstead, use a real HTML parser

很抱歉,如果我的答案感觉不实际,但几乎每天都会问这个问题,而且你的要求(在我看来)对正则表达式来说太复杂了。

此外,您的所有代码均未关闭。你应该这样写:

<p>paragraph goes here</p>

<li>goes here</li>
<li>list item 2</li>
<li>list item 3</li>

<p>another paragraph</p>

我的HTML可能已关闭,但您应真正关闭所有代码。

答案 2 :(得分:1)

我同意James和Chris,一般来说使用正确的解析器真的好多了,我看到人们以其他方式做错了(我假设你没有完全控制HTML)在这里输入,在这种情况下像正则表达式的快捷方式可能工作正常)。

我们假设你现在正在使用Java。如果您知道输入是有效的XHTML而不是HTML,则可以使用Sun Java JDK附带的Java API for XML Processing(JAXP)。然后在几行中,您可以将XHTML解析为DOM树,然后向下搜索列表的节点并随意执行任何操作。 JAXP有一个学习曲线,但它非常值得。

如果您使用的是Groovy,那就是XMLSlurper。 Ruby有几个很好的XML库。 PHP具有XMLParser扩展。 Python有Beautiful Soup。几乎任何现代语言都有很好的选择。

现在根据你的例子,你拥有正确的XML化的XHTML,而是带有未封闭标签和其他恶意软件的疯狂HTML。如果是这种情况,您需要获取一个HTML解析器库,大约为HTMLParser。祝你好运!

答案 3 :(得分:0)

假设所有元素都有结束标记,并且没有人通过在开始或结束标记中添加空格而变得聪明,并且某些元素在列表项之前,所有你必须这样做(在Perl语法中,可能与PCRE兼容)库,减去m//运算符):

m/(?<!li)>[^<]*<li/i

标识组中的第一个列表项。爆炸(使用x标志,以便于阅读):

m/
    (?<!li)> # the end of a start or end tag that isn't part of an li element
    [^<]*    # some non-angle-bracket characters -- in-between tag content
    <li      # the beginning of an li element
/xi          # space insensitive, case insensitive (respectively)

然后你可以更自信地通过下一个区块,列表项目之间不会发生任何事情,直到你读完它,保存那个位置,并再次使用这个模式。


如果没有解析器,弄清楚它的结束位置会更加棘手。你可以使用类似的东西(这是删节)

m/(?<=<li).*?<(div|form|p)/i

列出所有非内联元素,这将触发li和ul关闭并结束整个列表。但列表关闭隐含的另一种方法是关闭容器。


如果list-item元素本身格式正确(有结束标记),那么这可能足以放置列表的结束标记:

m{</li>.*?<(?!li)}i