我如何在嵌套的 dom 树中提取特定 dom 属性的列表?
How do i extract a list of specific dom-attributes in a nested dom tree?
我想遍历并收集具有data-table
属性的节点,提取其值,然后获取其具有data-field
或其他属性的子节点,并提取其将被保存的值作为列表。
从下面的Html示例中,我已经在[=38=中设置了dom-属性的锚点]-tree,意在将它们遍历并抽取后转化为模型结构
<body>
<div class="wrap" data-table="page"> Sample Text <p data-field="heading" class="format" >Welcome to this page</p>
<div class="flex-grid generic-card">
<h1 class="card " data-field="intro">Text </h1>
<div class="card " data-field="body"></div>
</div>
</div>
我希望最终结果是一个平面列表的形式,其中包含类似于 (page . ("title" "intro" "body"))
的内容
使用以下代码,我能够遍历节点并提取 'data-table'
,但问题是,我无法提取附加到 data-table
的 data-field
。
我没有成功地尝试使用递归方法,该方法包括重复 'dom-struct'
和 dom-search
函数的示例。
我注意到 libxml-parse-html-region''
returns 空字符串,在 dom 节点旁边有换行符,在解析 dom 树后会生成错误。
这段代码的目的是递归地从树中提取节点
(require 'dom)
(defun dom-struct (x)
(print (dom-attr x 'data-table)) ; extract the data-table attribute
(print (dom-tag (dom-node x))) ;extract dom-tag
(print (dom-children (dom-node x))) ; extract dom-children attached to a node but don't know how to extract data-field attribute
(print (dom-search (dom-children (dom-node x)) (lambda (node) (assq 'data-attribute (cadr node)))))
(mapconcat #'dom-struct (dom-children (dom-node x)) ""))
(defun macro-structify (tag-entries)
(with-temp-buffer
(insert tag-entries)
(let* ((mytags (libxml-parse-html-region (point-min) (point-max))))
(dom-struct (car (dom-by-tag mytags 'body))))))
(let ((myskel "<html>
<head>
<title>Demo: Gradient Slide</title>
</head>
<link href=\"https://fonts.googleapis.com/css?family=Nunito+Sans\" rel=\"stylesheet\">
<link rel=\"stylesheet\" href=\"dist/build.css\">
<body data-table=\"layout\">
<header data-field=\"title\">
<h1>Skeleton Screen</h1>
</header>
<div class=\"wrap\" data-table=\"page\"> Sample Text <p data-field=\"heading\" class=\"format\" data-attribute=\"somethingsomething\">Welcome to this page</p>
<div class=\"flex-grid generic-card\">
<div class=\"card loading\" data-field=\"intro\">Text </div>
<div class=\"card loading\" data-field=\"body\"></div>
</div>
</div>
</body>
</html>"))
(macro-structify myskel))
这是一个使用 esxml 包中的 esxml-query 的解决方案。它查找具有 data-field
属性的所有节点,这些节点是具有 data-table
属性的 div
节点的子节点,然后将它们的属性值收集到一个列表中。
(require 'dom)
(require 'esxml-query)
(let* ((myskel "<html>
<head>
<title>Demo: Gradient Slide</title>
</head>
<link href=\"https://fonts.googleapis.com/css?family=Nunito+Sans\" rel=\"stylesheet\">
<link rel=\"stylesheet\" href=\"dist/build.css\">
<body data-table=\"layout\">
<header data-field=\"title\">
<h1>Skeleton Screen</h1>
</header>
<div class=\"wrap\" data-table=\"page\"> Sample Text <p data-field=\"heading\" class=\"format\" data-attribute=\"somethingsomething\">Welcome to this page</p>
<div class=\"flex-grid generic-card\">
<div class=\"card loading\" data-field=\"intro\">Text </div>
<div class=\"card loading\" data-field=\"body\"></div>
</div>
</div>
</body>
</html>")
(dom (with-temp-buffer
(insert myskel)
(libxml-parse-html-region (point-min) (point-max))))
(table-node (esxml-query "div[data-table]" dom))
(model-nodes (esxml-query-all "[data-field]" table-node))
(model-data-table (dom-attr table-node 'data-table))
(model-data-fields (mapcar (lambda (node) (dom-attr node 'data-field)) model-nodes)))
(cons model-data-table model-data-fields))
;; => ("page" "heading" "intro" "body")
由于以下几个原因,结果与您指定的不同:
- 整个 HTML 片段包含一个带有
data-table
属性的 body
标签,然后是一个带有 data-table
属性的 div
标签,但是您的 HTML 片段查看后者,所以我更改了代码以查找具有 data-table
属性 的 div
标记
- 有一个
header
标签,其 data-field
属性设置为“title”(预期字段),但它是 body
标签的一部分,带有 data-table
属性设置为“布局”,而不是 data-table
属性设置为“页面”(实际字段)的 div
标签
- 其余字段符合预期,但打印与指定的不同,因为在许多 Lisp 语言中,
(foo . (bar baz))
与 (foo bar baz)
相同,通常以后一种形式打印
我想遍历并收集具有data-table
属性的节点,提取其值,然后获取其具有data-field
或其他属性的子节点,并提取其将被保存的值作为列表。
从下面的Html示例中,我已经在[=38=中设置了dom-属性的锚点]-tree,意在将它们遍历并抽取后转化为模型结构
<body>
<div class="wrap" data-table="page"> Sample Text <p data-field="heading" class="format" >Welcome to this page</p>
<div class="flex-grid generic-card">
<h1 class="card " data-field="intro">Text </h1>
<div class="card " data-field="body"></div>
</div>
</div>
我希望最终结果是一个平面列表的形式,其中包含类似于 (page . ("title" "intro" "body"))
使用以下代码,我能够遍历节点并提取 'data-table'
,但问题是,我无法提取附加到 data-table
的 data-field
。
我没有成功地尝试使用递归方法,该方法包括重复 'dom-struct'
和 dom-search
函数的示例。
我注意到 libxml-parse-html-region''
returns 空字符串,在 dom 节点旁边有换行符,在解析 dom 树后会生成错误。
这段代码的目的是递归地从树中提取节点
(require 'dom)
(defun dom-struct (x)
(print (dom-attr x 'data-table)) ; extract the data-table attribute
(print (dom-tag (dom-node x))) ;extract dom-tag
(print (dom-children (dom-node x))) ; extract dom-children attached to a node but don't know how to extract data-field attribute
(print (dom-search (dom-children (dom-node x)) (lambda (node) (assq 'data-attribute (cadr node)))))
(mapconcat #'dom-struct (dom-children (dom-node x)) ""))
(defun macro-structify (tag-entries)
(with-temp-buffer
(insert tag-entries)
(let* ((mytags (libxml-parse-html-region (point-min) (point-max))))
(dom-struct (car (dom-by-tag mytags 'body))))))
(let ((myskel "<html>
<head>
<title>Demo: Gradient Slide</title>
</head>
<link href=\"https://fonts.googleapis.com/css?family=Nunito+Sans\" rel=\"stylesheet\">
<link rel=\"stylesheet\" href=\"dist/build.css\">
<body data-table=\"layout\">
<header data-field=\"title\">
<h1>Skeleton Screen</h1>
</header>
<div class=\"wrap\" data-table=\"page\"> Sample Text <p data-field=\"heading\" class=\"format\" data-attribute=\"somethingsomething\">Welcome to this page</p>
<div class=\"flex-grid generic-card\">
<div class=\"card loading\" data-field=\"intro\">Text </div>
<div class=\"card loading\" data-field=\"body\"></div>
</div>
</div>
</body>
</html>"))
(macro-structify myskel))
这是一个使用 esxml 包中的 esxml-query 的解决方案。它查找具有 data-field
属性的所有节点,这些节点是具有 data-table
属性的 div
节点的子节点,然后将它们的属性值收集到一个列表中。
(require 'dom)
(require 'esxml-query)
(let* ((myskel "<html>
<head>
<title>Demo: Gradient Slide</title>
</head>
<link href=\"https://fonts.googleapis.com/css?family=Nunito+Sans\" rel=\"stylesheet\">
<link rel=\"stylesheet\" href=\"dist/build.css\">
<body data-table=\"layout\">
<header data-field=\"title\">
<h1>Skeleton Screen</h1>
</header>
<div class=\"wrap\" data-table=\"page\"> Sample Text <p data-field=\"heading\" class=\"format\" data-attribute=\"somethingsomething\">Welcome to this page</p>
<div class=\"flex-grid generic-card\">
<div class=\"card loading\" data-field=\"intro\">Text </div>
<div class=\"card loading\" data-field=\"body\"></div>
</div>
</div>
</body>
</html>")
(dom (with-temp-buffer
(insert myskel)
(libxml-parse-html-region (point-min) (point-max))))
(table-node (esxml-query "div[data-table]" dom))
(model-nodes (esxml-query-all "[data-field]" table-node))
(model-data-table (dom-attr table-node 'data-table))
(model-data-fields (mapcar (lambda (node) (dom-attr node 'data-field)) model-nodes)))
(cons model-data-table model-data-fields))
;; => ("page" "heading" "intro" "body")
由于以下几个原因,结果与您指定的不同:
- 整个 HTML 片段包含一个带有
data-table
属性的body
标签,然后是一个带有data-table
属性的div
标签,但是您的 HTML 片段查看后者,所以我更改了代码以查找具有data-table
属性 的 - 有一个
header
标签,其data-field
属性设置为“title”(预期字段),但它是body
标签的一部分,带有data-table
属性设置为“布局”,而不是data-table
属性设置为“页面”(实际字段)的div
标签 - 其余字段符合预期,但打印与指定的不同,因为在许多 Lisp 语言中,
(foo . (bar baz))
与(foo bar baz)
相同,通常以后一种形式打印
div
标记