php - 通过正则表达式解析 HTML 最深匹配优先
问题描述
我正在尝试将 HTML 有序/无序列表递归解析为 OOP 结构并偶然发现了一个问题。假设我有这段代码:
$text = '
<ol>
<li>
<ul>
<li>aaa</li>
<li>bbb</li>
</ul>
</li>
<li>fff</li>
<li>
<ol>
<li>ccc</li>
<li>ddd</li>
</ol>
</li>
</ol>
';
preg_match_all("/<ol>(.+?)<\/ol>/mis", $text, $matches);
问题是贪婪或懒惰的匹配似乎尽可能地浅:我想要的是相反,从最深到最浅,所以上面的表达式应该匹配:
<ol>
<li>ccc</li>
<li>ddd</li>
</ol>
任何想法?
解决方案
RegEx 应该只用于从 HTML 中提取特定数据(将其视为文本)。更多信息
将 HTML 解析为 OOP 结构是 DOMDocument::loadHTML() 所做的。OOP 结构是标准化的 DOM。使用 DOM 方法和 Xpath 表达式,您可以遍历、读取和操作数据。
$document = new DOMDocument();
$document->loadHTML($text);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('//li[not(.//li)]') as $liLeaf) {
echo "LABEL: ", $liLeaf->textContent, "\n";
echo "INDEX: ", $xpath->evaluate('count(preceding-sibling::li)', $liLeaf), "\n";
echo "LEVEL: ", $xpath->evaluate('count(ancestor::*[self::ol or self::ul])', $liLeaf), "\n";
echo "IN: ", $xpath->evaluate('local-name(parent::*)', $liLeaf), "\n";
echo "\n";
}
输出:
LABEL: aaa
INDEX: 0
LEVEL: 2
IN: ul
LABEL: bbb
INDEX: 1
LEVEL: 2
IN: ul
LABEL: fff
INDEX: 1
LEVEL: 1
IN: ol
LABEL: ccc
INDEX: 0
LEVEL: 2
IN: ol
LABEL: ddd
INDEX: 1
LEVEL: 2
IN: ol
推荐阅读
- python - 如何对唯一列表使用列表理解?
- nginx - Linkerd 使用 Nginx 入口控制器拆分流量
- android - YYYY 日期格式在一台设备上返回 2021,在另一台设备上返回 2020
- php - 为什么最后一个 h2 标题不显示内容?
- apache-spark - 如何在 PySpark 中使用 StandardScaler 标准化测试数据集?
- c++ - 在 OpenCV C++ 上录制窗口的视频
- android - 使用 ADB 获取安卓游戏的 FPS
- node.js - 分段错误(核心转储)错误 139(Webpack 5.11.1)
- http-live-streaming - HLS FLAC 音频流
- c - 如何在c中添加布尔值?