我被告知并经常看到别人被告知:不要使用正则表达式来解析(或“解析”)用 HTML,XML等语言编写的文档.名称的原因各不相同,在这里并不重要.

当被问及做什么时,通常会将您引用到库中来解析这样的文档 – PHP扩展,JS框架等.大多数时候它们似乎依赖于文档对象模型.

我的问题不是如何在程序或脚本中执行此操作.在实际情况下,我不会尝试再次发明轮子,而只是使用一个可用的框架.

我想知道的是 – 这些框架是如何做到的?或者如果没有框架(假设)我该怎么做?我不是在谈论具体的任何语言,我对从文档中提取信息背后的理论感兴趣.

解析XML需要一种能够识别称为“无上下文语言”的工具.正则表达式识别常规语言,它是无上下文语言的子集.

识别常规语言

正则语言由确定性有限自动机(DFA)识别. DFA是一组状态之间具有转换边缘的状态,以及一个输入缓冲区(您要解析的字符串). DFA从其开始状态开始. DFA读取输入缓冲区开头的字符,告诉它要进行哪个转换.这会将DFA移动到下一个状态,然后重复该过程.如果DFA遇到输入字符,它没有转换,则结束(输入无法识别).如果DFA达到指定的结束状态,则已识别输入

要记住的最重要的事情是,DFA不记得他们去过的状态 – 就在他们现在的位置,以及接下来的位置.这使得DFA无法识别某些类型的语言,例如匹配的XML标记.

正则表达式实现(如PCRE)有一些方便的扩展(例如”,’?’和字符类),以及其他改变正则表达式(如前瞻和后引用)功能的扩展.这些正则表达式比DFA更强大,但仅使用这些扩展的正则表达式构建XML解析器是很困难或不可能的.

识别无上下文语言

下推自动机识别无上下文语言.这些工作就像DFA一样,但增加了堆栈.下推自动机使用输入的第一个字符和堆栈顶部的值选择转换.在每个步骤中,机器消耗一个输入字符,可以在堆栈上推送一个值,弹出一个或对堆栈不执行任何操作.

下推自动机可以使用堆栈来记住它们的位置,这使它们适合解析XML(或大多数编程语言,除了一些特殊例外)之类的语言.

解析XML

解析器不是通过设计下推自动机来构建的,就像通过设计DFA而无法识别常规语言一样.无上下文语法是描述无上下文语言的更好方法.它们通常以Backus-Naur形式(BNF)写下来.这是XML子集的简单BNF语法:

Tags ::= Tag Tags | <nothing>

Tag ::= "<" /[a-zA-Z]+/ Attributes ">" Document "</" /[a-zA-Z]+/ ">"

Attributes ::= Attribute Attributes | <nothing>

Attribute ::= /[a-zA-Z]+/ "=" "\"" /[a-zA-Z0-9 ]+/ "\""

该语法由非终端(“标签”,“标签”,“属性”和“属性”)组成.非终端显示在规则右侧的任何地方,可以用任何可能的定义(由|分隔)替换.引号和正则表达式中的文本是终端,它必须与输入完全匹配.

标签非终端识别开始和结束标签,标签之间是非终端标签.每当解析器识别出开始标记时,它都希望在另一侧找到结束标记.标签将识别一个标签,然后再标记标签.此递归定义允许解析器识别无限数量的标记.

解析器生成器是将无上下文语法转换为下推自动机以识别输入语言的工具.虽然在准确指定语法方面存在许多挑战,但这会在构建解析器时带来很多复杂性.

其他解析方法

您可以编写解析器而无需手动构建状态机,也可以编写无上下文语法.通常,这可以通过递归下降解析器或手工解析器来完成,该解析器使用具有关于被解析语言的一些特殊知识的正则表达式.递归下降解析器看起来很像无上下文语法,但有一些严重的性能问题和功能限制.还有解析表达式语法(PEG),其工作方式类似于正则表达式和BNF语法的混合.维基百科上有很多关于所有这些技术的文章,还有很多可用于构建各种解析器的工具.

正则表达式 – 如何解析HTML/XML文档?的更多相关文章

  1. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. xcode – Cordova plugin.xml添加“Header Search Paths”条目

    我希望将Cordova插件添加到Xcode项目后,在“HeaderSearchPaths”下添加一个新条目.如何在Cordovaplugin.xml文件中进行配置?

  3. ios – 有关多个连接/提要/视图的XML解析的设计/实现建议

    >我应该在每个视图中都有解析器类/对象或解析XML提要吗?

  4. ios – 使用大写符号在字符串swift中获取URL的正则表达式

    我尝试在文本中获取URL.所以,在此之前,我使用了这样一个表达式:但是当用户输入带有大写符号的URL时(例如Http://Google.com,它与它不匹配)我遇到了问题.我试过了:但什么都没发生.解决方法您可以使用正则表达式中的i内联标志关闭区分大小写,有关可用正则表达式功能的详细信息,请参阅FoundationFrameworkReference.(?ismwx-ismwx)Flagsetti

  5. ios – 如何在Swift 3中使用正则表达式?

    解决方法我相信.当没有其他选项适用时,将使用.allZeros.因此,使用Swift3,您可以传递一个空的选项列表或省略options参数,因为它默认为无选项:要么请注意,在Swift3中,您不再使用error参数.它现在抛出.

  6. iOS的相当于Android的colors.xml的是什么?

    如果没有,组织整个应用程序使用的颜色的最佳方法是什么?

  7. ios – lldb断点在类目标c中的所有方法

    如何使用lldb在ObjectiveC类中的所有方法上自动设置断点?

  8. iOS中的XML转换为JSON

    我需要将XML响应转换为JSON.我的XML响应:我正在使用本网站的XMLReader支持文件:XMLReader我正在使用此代码将XML转换为JSON我收到了JSON响应:我需要这样的回应:我在线转换时得到这个回应.如何获得这样的回应提前致谢.解决方法此代码不会将任何内容转换为JSON.它给你一个NSDictionary.您需要从字典中实际创建JSON数据.尝试这个大小.

  9. ios – Info.plist格式不正确

    解决方法plist文件是严格指定格式的XML文档;XML和PropertyList结构都有非常严格的规则.如果您尝试手动编辑info.plist(即文本),您可以轻松搞砸事情,方法是打开Asas>源代码:您不太可能正确使用此格式.因此,您应该始终使用OpenAs>编辑info.plist.物业清单:这允许属性列表编辑器为您生成XML,并且不太可能在生成的XML结构中出错.当然,我想你仍然可能搞砸某些东西的价值……

  10. ios – 在没有XML的情况下更新sqlite数据库

    我的应用程序需要来自sqlite数据库的数据.它将附带此数据库的一个版本,但我需要定期更新它(很可能每月一次).通常情况下,我一直在通过我设置的一堆网络服务将我的应用程序的其他部分的更新作为XML发送,但我现在正在处理的这个特定数据库非常大(大约20-30MB),而且我当我尝试以这种方式发送时出现超时错误.我尝试将数据库放在我的公司服务器上,然后将其下载到NSData对象中.然后我将该数据对象保存

随机推荐

  1. 法国电话号码的正则表达式

    我正在尝试实施一个正则表达式,允许我检查一个号码是否是一个有效的法国电话号码.一定是这样的:要么:这是我实施的但是错了……

  2. 正则表达式 – perl分裂奇怪的行为

    PSperl是5.18.0问题是量词*允许零空间,你必须使用,这意味着1或更多.请注意,F和O之间的空间正好为零.

  3. 正则表达式 – 正则表达式大于和小于

    我想匹配以下任何一个字符:或=或=.这个似乎不起作用:[/]试试这个:它匹配可选地后跟=,或者只是=自身.

  4. 如何使用正则表达式用空格替换字符之间的短划线

    我想用正则表达式替换出现在带空格的字母之间的短划线.例如,用abcd替换ab-cd以下匹配字符–字符序列,但也替换字符[即ab-cd导致d,而不是abcd,因为我希望]我如何适应以上只能取代–部分?

  5. 正则表达式 – /bb | [^ b] {2} /它是如何工作的?

    有人可以解释一下吗?我在t-shirt上看到了这个:它似乎在说:“成为或不成为”怎么样?我好像没找到’e’?

  6. 正则表达式 – 在Scala中验证电子邮件一行

    在我的代码中添加简单的电子邮件验证,我创建了以下函数:这将传递像bob@testmymail.com这样的电子邮件和bobtestmymail.com之类的失败邮件,但是带有空格字符的邮件会漏掉,就像bob@testmymail也会返回true.我可能在这里很傻……当我测试你的正则表达式并且它正在捕捉简单的电子邮件时,我检查了你的代码并看到你正在使用findFirstIn.我相信这是你的问题.findFirstIn将跳转所有空格,直到它匹配字符串中任何位置的某个序列.我相信在你的情况下,最好使用unapp

  7. 正则表达式对小字符串的暴力

    在测试小字符串时,使用正则表达式会带来性能上的好处,还是会强制它们更快?不会通过检查给定字符串的字符是否在指定范围内比使用正则表达式更快来强制它们吗?

  8. 正则表达式 – 为什么`stoutest`不是有效的正则表达式?

    isthedelimiter,thenthematch-only-onceruleof?PATTERN?

  9. 正则表达式 – 替换..与.在R

    我怎样才能替换..我尝试过类似的东西:但它并不像我希望的那样有效.尝试添加fixed=T.

  10. 正则表达式 – 如何在字符串中的特定位置添加字符?

    我正在使用记事本,并希望使用正则表达式替换在字符串中的特定位置插入一个字符.例如,在每行的第6位插入一个逗号是什么意思?如果要在第六个字符后添加字符,请使用搜索和更换从技术上讲,这将用MatchGroup1替换每行的前6个字符,后跟逗号.

返回
顶部