您能否提供一些示例,说明为什么用正则表达式很难解析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楼
我认为问题可以归结为:
正则表达式几乎总是错误的。 存在合法输入,它将无法正确匹配。 如果您足够努力,则可以使它达到99%正确或99.999%的正确性,但是几乎不可能使它达到100%的正确性,这仅仅是由于XML使用实体允许的怪异事物。
如果正则表达式不正确,即使对于0.00001%的输入来说,则正则表达式也存在安全问题,因为有人会发现一个输入会破坏您的应用程序。
如果正则表达式足够正确,可以覆盖99.99%的情况,那么它将完全无法阅读和维护。
正则表达式很可能在中等大小的输入文件上表现很差。 我与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="<img>">
XHTML和XML的正确版本是
<img src="imgtag.gif" alt="<img>"/>
您提供的以下示例也无效
<
tag
attr="5"
/>
这也不是有效的HTML或XML。 标记的名称必须在'<'后面,尽管属性和结尾的'>'可能在他们想要的任何位置。 所以有效的XML实际上是
<tag
attr="5"
/>
这是另一个有趣的功能:您实际上可以选择使用“或”作为属性引号字符
<img src="data: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>&<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
您能否提供一些示例,说明为什么用正则表达式很难解析XML和HTML? [关闭]相关推荐
- 下载和安装MySQL官方提供的示例数据库(Employees)
一.前言 在此之前笔者写过一篇博客<你说精通MySQL其实很菜jī(1):你不一定会的基本技巧或知识点(值得一看)>,本文内容是从那篇博客截取出来的.我们要学习MySQL相关的技术点, ...
- 应用笔记 UHD提供的示例 Ettus Research
简介 本文将提供UHD代码示例UHD 是由Ettus Research研发的一款驱动器,能和所有的USRP™ 软件定义无线电兼容, UHD可在多个操作系统中(包括Linux, Windows and ...
- python解析xml文件elementtree_Python中使用ElementTree解析XML示例
[XML基本概念介绍] XML 指可扩展标记语言(eXtensible Markup Language). XML 被设计用来传输和存储数据. 概念一: 复制代码 代码如下: # foo元素的起始标签 ...
- jdom解析xml文件_JDOM编辑XML文件示例
jdom解析xml文件 JDOM provides very neat way to manipulate XML files, using JDOM is very easy and the cod ...
- 四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)
众所周知,现在解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 下面首先给出这四种方法的jar包下载地址 DOM:在现在的Java JDK里都自带了,在xml- ...
- php获得帮助类数据_PHP解析xml格式数据工具类示例
本文实例讲述了PHP解析xml格式数据工具类.分享给大家供大家参考,具体如下: class ome_xml { /** * xml资源 * * @var resource * @see xml_par ...
- Qt解析XML及QTableWidget用法示例
#include "widget.h" #include "ui_widget.h" #include <QFile> #include <Q ...
- java解析xml实例_在java中使用dom解析xml的示例分析
本篇文章介绍了,在java中使用dom解析xml的示例分析.需要的朋友参考下 dom是个功能强大的解析工具,适用于小文档 为什么这么说呢?因为它会把整篇xml文档装载进内存中,形成一颗文档对象树 总之 ...
- java解析xml工具类_通过dom4j解析XML字符串XMLDocUtil工具类转换为XML文档及获取指定根节点及指定节点路径内容代码示例...
一.前言 通过dom4j解析XML文档的XMLDocUtil工具类,进行解析xml字符串为Document文档对象.获取根节点元素路径内容getRootElement.获取唯一路径节点的值getSin ...
最新文章
- java 转换成时间戳_Java 实例 – 时间戳转换成时间 - Java 基础教程
- Mat转CImage
- 【论文解读】ICLR 2021丨当梯度提升遇到图神经网络,“鱼和熊掌”皆可兼得
- Java 异步编程:从 Future 到 Loom
- Android之解决NestedScrollView嵌套RecyclerView部分手机返回到这个页面Recyclerview顶部,而不是页面NestedScrollView顶部
- Android导入第三方静态库.a编译成动态库.so
- linux下安装yum步骤
- python图像灰度化、二值化
- 海森矩阵(Hessian)
- JavaWeb-HTML
- java冰箱评测开题报告范文_智能电冰箱控制的设计开题报告.doc
- [洛谷P3987]我永远喜欢珂朵莉~
- 【BUG】unresolvable R_ARM_THM_CALL relocation against symbol `strlen'
- 移动硬盘插入提示需要格式化RAW_移动硬盘数据恢复 – 图文教程
- uchome的安装记录
- 谷歌雅虎新闻大战-两种路线的PK
- android的数据存储(3)(LitePal)
- 单片机搭建环境烧录方法_万物互联-stm32单片机简介、烧录、编程及其项目环境搭建...
- Linux内存是怎么工作的?
- java连不上sqlserver_java和SQL连接不上——解决步骤