首页 > 解决方案 > 如何解析 HTML 文档中的不同元素(在 Dart/Flutter 中)并保持顺序不变

问题描述

例如。一个标题,然后是图像,然后是一些文本,然后是另一个图像,然后是一些文本。

我真的需要与此等价的:html.getElementsByTagName('title' or 'p' or 'whatever-else-I-need')。然后我可以在循环中处理并在正确排序的列表中输出我的模型。

解析不同元素标签/数据类型的序列关键信息一定是常见的。非常感激。

标签: htmldartparsing

解决方案


我不是专家package:html(也不是一般的 HTML 和 CSS),但我认为您可以使用Document.querySelectorAll适当的选择器字符串:

import 'package:html/parser.dart' as html;

void main() {
  var htmlStr = r'''\
<html>
<head>
<title>My title</title>
</head>
<body>
<p>Lorem ipsum</p>
<img src="foo.png">
</body>
</html>  
''';
  var document = html.parse(htmlStr);
  var elements = document.querySelectorAll('title,p,img');
  elements.forEach(print);
  // Prints: 
  // <html title>
  // <html p>
  // <html img>
}

如果选择器不符合您的要求,您可以编写一个遍历树的函数:

import 'package:html/dom.dart' as dom;

/// Walks [document] and invokes [elementCallback] on each element using a preorder
/// traversal.
///
/// [elementCallback] should return true to continue walking the tree, false to
/// abort.
void walk(dom.Document document, bool Function(dom.Element) elementCallback) {
  var stack = <dom.Element>[];
  stack.addAll(document.children.reversed);
  while (stack.isNotEmpty) {
    var element = stack.removeLast();
    if (!elementCallback(element)) {
      break;
    }
    stack.addAll(element.children.reversed);
  }
}

然后您可以walk使用适当的回调运行,有条件地将每个回调添加Element到 some List,例如:

var elements = <Element>[];
var wantedTags = {'title', 'p', 'img'};
walk(document, (element) {
  if (wantedTags.contains(element.localName)) {
    elements.add(element);
  }
  return true;
});

推荐阅读