lxml:不解析子树,而是将其视为二进制内容

lxml: Do not parse subtree but treat as binary content

我正在处理 XML 内容,其中包含的元素可能包含格式不正确的 XML/markup-like(例如 HTML)文本内容。例如:

<root>
    <data>
        <x>foo<y>bar</y>
    </data>
    <data>
        <z>foo<y>bar</y>
    </data>
</root>

目标:我希望lxml.etree不要尝试将data元素下的任何内容解析为XML,而只是[=56] =] 它是 bytesstr(可以是 elem.text)。

文件很大,我想用lxml.etree.iterparse提取在data中找到的内容- 元素。

初始想法:获取元素内容(在本例中包含 data 开始和结束标记)的一种直接方法可能是:

data = BytesIO(b"""
<root>
    <data>
        <x>foo<y>bar</y>
    </data>
    <data>
        <z>foo<y>bar</y>
    </data>
</root>
""")

from lxml import etree

# see below why html=True
context = etree.iterparse(data, events=("end",), tag=("data",), html=True)
contents = []  # I don't keep lists in the "real" application
for event, elem in context:
    contents.append(etree.tostring(elem))  # get back the full content underneath data

问题 lxml.etree 可以 运行 解析 data 的子项(例如:我已经当 html 数据存储在 data 下时,使用 html=True 不会 运行 出现问题)。我知道 lxml 中有 custom element classes,但根据我对文档的理解,它们不会改变 lxml.etreelibxml2) 规定的解析行为。

有什么简单的方法可以告诉 lxml 不要尝试将元素内容解析为子元素。应用程序本身受益于其他 lxml 功能,如果我单独为 data 编写自定义提取器,我将不得不复制这些功能。

或者是否可以使用 XSLT 首先转换输入以在 lxml 中进行处理,然后再 link 返回数据?

这是否按预期工作? XML 通过添加 DTD 和 CDATA 进行修改,以指定数据元素中的内容必须被视为字符数据。

data = io.BytesIO(B'''<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE root [
<!ELEMENT root (data+)>
<!ELEMENT data (#PCDATA)>
]>

<root>
    <data>
        <![CDATA[
        <x>foo<y>bar</y>
        ]]>
    </data>
    <data>
        <![CDATA[
        <z>foo<y>bar</y>
        ]]>
    </data>
</root>

''')

from lxml import etree

# see below why html=True
context = etree.iterparse(data, events=("end",), tag=("data",), dtd_validation=True, load_dtd=True)
contents = []  # I don't keep lists in the "real" application
for event, elem in context:
    contents.append(etree.tostring(elem))  # get back the full content underneath data