为什么 lxml 在解析时关闭这个 "ol" 标签?
Why is lxml closing this "ol" tag when parsing?
这是一些 HTML:
<ol><ul><li>item</li></ul></ol>
和一些 python 3 代码 lxml
解析并重新打印:
import sys
from lxml import etree, html
document_root = html.fromstring(sys.stdin.read())
print(etree.tostring(document_root, encoding='unicode'))
这是输出:
<div><ol/><ul><li>item</li></ul>
</div>
在输出中,lxml
在 ul
开始之前关闭了 ol
,这改变了列表结构。
为什么要这样做?
我可以让 lxml
以保留列表结构的方式解析 HTML 吗?
编辑:请注意,如果我将 ul
替换为 ol
(<ol><ol><li>item</li></ol></ol>
),或者如果我替换 ol
与 ul
(<ul><ul><li>item</li></ul></ul>
)。输出与输入没有变化。
我无法控制 HTML,它可能来自任何地方。
我正在使用从 PyPi 安装的 lxml 4.6.3,以及 python 3.9。
或者,是否有另一种解析 HTML 的方法,我可以从中提取列表文本并保留 Python 中的列表结构?
如你所知,我正在使用 lxml 来删除属性,所以下面是更接近我的用例的代码。不过,我想先给出最小的可复现的测试用例。
更接近我的用例的代码:
import sys
import lxml.html.clean as clean
from lxml import etree, html
document_root = html.fromstring(sys.stdin.read())
cleaner = clean.Cleaner(safe_attrs_only=True, safe_attrs=frozenset())
cleansed = cleaner.clean_html(document_root)
# Do something with the lists in cleansed, defined by ol, ul, and li ..
print(etree.tostring(cleansed, encoding='unicode')
我认为 HTML 4 和 HTML5 都不允许 ul
元素作为 ol
元素的子元素。只有 li
个元素可以是直接子元素。
这可能就是为什么 HTML 解析器构建的树结构不代表输入标记中的嵌套。 “传统的”HTML 4 解析器,就像可能在 lxml's/libxml 的 HTML 解析器算法中实现的那样,是否对结构进行了相同的更改,我不记得了,我我不确定在哪里测试它。
虽然两个 HTML5 验证器将您的 ul
标记为 ol
的不允许的子代,但当前的浏览器似乎保留了该嵌套。
这是一些 HTML:
<ol><ul><li>item</li></ul></ol>
和一些 python 3 代码 lxml
解析并重新打印:
import sys
from lxml import etree, html
document_root = html.fromstring(sys.stdin.read())
print(etree.tostring(document_root, encoding='unicode'))
这是输出:
<div><ol/><ul><li>item</li></ul>
</div>
在输出中,lxml
在 ul
开始之前关闭了 ol
,这改变了列表结构。
为什么要这样做?
我可以让 lxml
以保留列表结构的方式解析 HTML 吗?
编辑:请注意,如果我将 ul
替换为 ol
(<ol><ol><li>item</li></ol></ol>
),或者如果我替换 ol
与 ul
(<ul><ul><li>item</li></ul></ul>
)。输出与输入没有变化。
我无法控制 HTML,它可能来自任何地方。
我正在使用从 PyPi 安装的 lxml 4.6.3,以及 python 3.9。
或者,是否有另一种解析 HTML 的方法,我可以从中提取列表文本并保留 Python 中的列表结构?
如你所知,我正在使用 lxml 来删除属性,所以下面是更接近我的用例的代码。不过,我想先给出最小的可复现的测试用例。
更接近我的用例的代码:
import sys
import lxml.html.clean as clean
from lxml import etree, html
document_root = html.fromstring(sys.stdin.read())
cleaner = clean.Cleaner(safe_attrs_only=True, safe_attrs=frozenset())
cleansed = cleaner.clean_html(document_root)
# Do something with the lists in cleansed, defined by ol, ul, and li ..
print(etree.tostring(cleansed, encoding='unicode')
我认为 HTML 4 和 HTML5 都不允许 ul
元素作为 ol
元素的子元素。只有 li
个元素可以是直接子元素。
这可能就是为什么 HTML 解析器构建的树结构不代表输入标记中的嵌套。 “传统的”HTML 4 解析器,就像可能在 lxml's/libxml 的 HTML 解析器算法中实现的那样,是否对结构进行了相同的更改,我不记得了,我我不确定在哪里测试它。
虽然两个 HTML5 验证器将您的 ul
标记为 ol
的不允许的子代,但当前的浏览器似乎保留了该嵌套。