您能否提供一些示例,说明为什么用正则表达式很难解析XML和HTML? [关闭]

我看到人们一遍 又一遍地犯的一个错误是试图用正则表达式解析XML或HTML。 以下是难以解析XML和HTML的一些原因:

人们希望将文件视为一系列行,但这是有效的:

<tag
attr="5"
/>

人们希望将<或<tag视为标签的开头,但是类似的东西却普遍存在:

<img src="imgtag.gif" alt="<img>" />

人们通常希望将开始标签与结束标签匹配,但是XML和HTML允许标签包含它们自己(传统的正则表达式根本无法处理):

<span id="outer"><span id="inner">foo</span></span> 

人们通常希望将其与文档内容进行匹配(例如著名的“在给定页面上查找所有电话号码”问题),但是数据可能会被标记(即使在查看时看起来很正常):

<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>

注释可能包含格式不正确或不完整的标签:

<a href="foo">foo</a>
<!-- FIXME:
    <a href="
-->
<a href="bar">bar</a>

您还知道其他哪些陷阱?


#1楼

我很想说“不要重新发明轮子”。 除了XML是一种非常非常复杂的格式。 因此,也许我应该说“不要重新发明同步加速器”。

也许正确的陈词滥调始于“当您只有锤子...”时,您知道如何使用正则表达式,正则表达式擅长解析,那么为什么还要花时间学习XML解析库呢?

因为解析XML很困难 。 您不必学习使用XML解析库而节省的任何工作,将远远超过您必须要做的创造性工作和减少错误的工作。 为了您自己的利益,谷歌“ XML库”并利用他人的工作。


#2楼

一般来说,由于XML语法绝非常规,因此无法使用正则表达式来解析XML。 简而言之,正则表达式无法计数(嗯,Perl正则表达式实际上可以计数),因此您无法平衡开闭标签。

我不同意。 如果要在正则表达式中使用递归,则可以轻松找到打开和关闭标签。

在这里,我展示了正则表达式的示例,以避免解析第一条消息中的示例错误。


#3楼

我认为问题可以归结为:

  1. 正则表达式几乎总是错误的。 存在合法输入,它将无法正确匹配。 如果您足够努力,则可以使它达到99%正确或99.999%的正确性,但是几乎不可能使它达到100%的正确性,这仅仅是由于XML使用实体允许的怪异事物。

  2. 如果正则表达式不正确,即使对于0.00001%的输入来说,则正则表达式也存在安全问题,因为有人会发现一个输入会破坏您的应用程序。

  3. 如果正则表达式足够正确,可以覆盖99.99%的情况,那么它将完全无法阅读和维护。

  4. 正则表达式很可能在中等大小的输入文件上表现很差。 我与XML的第一次接触是用一个正确的XML解析器替换一个(错误地)解析传入XML文档的Perl脚本,我们不仅将300行不可读的代码替换为任何人都可以理解的100行,而且还改善了用户响应时间从10秒到大约0.1秒。


#4楼

在这里对这个问题给出了简化的答案。 虽然它不占100%的标记,但我解释了如果您愿意做一些预处理工作,那怎么可能。


#5楼

这取决于您“解析”的意思。 一般来说,由于XML语法绝非常规,因此无法使用正则表达式来解析XML。 简而言之,正则表达式无法计数(嗯,Perl正则表达式实际上可以计数),因此您无法平衡开闭标签。


#6楼

我写了一个关于此主题的完整博客文章: 正则表达式限制

问题的症结在于HTML和XML是递归结构,需要计数机制才能正确解析。 真正的正则表达式无法计数。 您必须具有上下文无关的语法才能计数。

上一段带有一些警告。 现在,某些正则表达式实现支持递归的想法。 但是,一旦开始将递归添加到正则表达式中,您实际上就在扩展边界,应该考虑使用解析器。


#7楼

人们通常会默认编写贪婪模式,这通常会导致不加思索地通过。*将大块文件吞入尽可能大的<foo>。* </ foo>中。


#8楼

其实

<img src="imgtag.gif" alt="<img>" />

是无效的HTML,也不是有效的XML。

这不是有效的XML,因为'<'和'>'在属性字符串中不是有效的字符。 需要使用相应的XML实体&lt; 和&gt;

它也不是有效的HTML,因为HTML中不允许使用短结束符(但在XML和XHTML中是正确的)。 根据HTML 4.01规范,“ img”标签也是隐式关闭的标签。 这意味着手动关闭它实际上是错误的,并且等同于关闭任何其他标签两次。

HTML的正确版本是

<img src="imgtag.gif" alt="&lt;img&gt;">

XHTML和XML的正确版本是

<img src="imgtag.gif" alt="&lt;img&gt;"/>

您提供的以下示例也无效

<
tag
attr="5"
/>

这也不是有效的HTML或XML。 标记的名称必须在'<'后面,尽管属性和结尾的'>'可能在他们想要的任何位置。 所以有效的XML实际上是

<tag
attr="5"
/>

这是另一个有趣的功能:您实际上可以选择使用“或”作为属性引号字符

<img src="image.gif" alt='This is single quoted AND valid!'>

发布的所有其他原因都是正确的,但解析HTML的最大问题是人们通常无法正确理解所有语法规则。 您的浏览器将您的tagoup解释为HTML的事实并不意味着您实际上已经编写了有效的HTML。

编辑:甚至stackoverflow.com也同意我关于有效和无效的定义。 您的无效XML / HTML未突出显示,而我的更正版本则未突出显示。

基本上,XML不能使用正则表达式进行解析。 但是也没有理由这样做。 每种语言都有很多许多XML解析器。 您可以在SAX解析器,DOM解析器和Pull解析器之间进行选择。 所有这些保证都比使用正则表达式解析要快得多,然后您可以在结果DOM树上使用XPath或XSLT之类的出色技术。

因此,我的回答是:用正则表达式解析XML不仅很困难,而且也不是一个好主意。 只需使用数百万个现有XML解析器之一,即可利用XML的所有高级功能。

HTML太难了,甚至无法尝试自己解析。 首先,法律语法具有许多您可能不知道的细微之处,其次,狂野的HTML只是一大堆令人讨厌的东西(您不知所措)。 有各种各样的松散解析器库可以很好地处理诸如标记汤之类的HTML,只需使用它们即可。


#9楼

人们实际上是使用正则表达式犯了一个错误,还是仅仅足以胜任他们要完成的任务?

我完全同意,无法使用正则表达式解析html和xml,因为其他人已经回答了。

但是,如果您的要求不是解析html / xml,而是仅获取html / xml的“已知良好”位中的一小部分数据,那么正则表达式甚至是更简单的“子字符串”就足够了。


#10楼

这是一些有趣的有效XML:

<!DOCTYPE x [ <!ENTITY y "a]>b"> ]>
<x>
    <a b="&y;>" />
    <![CDATA[[a>b <a>b <a]]>
    <?x <a> <!-- <b> ?> c --> d
</x>

这一点欢乐就是有效的HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" [
    <!ENTITY % e "href='hello'">
    <!ENTITY e "<a %e;>">
]>
    <title>x</TITLE>
</head>
    <p id  =  a:b center>
    <span / hello </span>
    &amp<br left>
    <!---- >t<!---> < -->
    &e link </a>
</body>

更不用说针对无效构造的所有特定于浏览器的解析。

祝您好运,正则表达式!

编辑(JörgW Mittag):这是格式良好,有效的HTML 4.01的另一个不错的片段:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd"> 
<HTML/
  <HEAD/
    <TITLE/>/
    <P/>

#11楼

不在列表中的一个陷阱是属性可以以任何顺序出现,因此,如果您的正则表达式正在查找带有href“ foo”和类“ bar”的链接,则它们可以以任何顺序出现,并且可以具有任意其他数量他们之间的事情。


#12楼

我相信这本 经典的书可以为您提供所需的信息。 您可以在其中的评论之一中找到要点:

我认为这里的缺陷是HTML是Chomsky Type 2语法(无上下文语法),而RegEx是Chomsky Type 3语法(正则表达式)。 由于类型2语法从本质上比类型3语法复杂-您不可能希望做到这一点 。 但是很多人会尝试,有些人会宣称成功,而另一些人会发现错误并完全把你弄糟。

来自Wikipedia的更多信息: Chomsky Hierarchy

发布了0 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/asdfgh0077/article/details/104221284
今日推荐