我正在编写一个方法来解析 HTML 字符串,查询并获取一些节点,然后输出这些节点的 HTML。
我正在使用libxml,并且已成功加载和解析输入HTML,并输出我想要的节点的HTML字符串,除了我想要保留任何HTML实体和libxml似乎将它们转换为相关的 UTF-8 字符。
这是我到目前为止所得到的(代码是 Objective-C 项目的一部分):
NSString *HTMLString = ...
NSData *documentData = [HTMLString dataUsingEncoding:NSUTF8StringEncoding];
//Create the document
xmlDocPtr doc = htmlReadMemory([documentData bytes],
[documentData length],
"",
NULL,
HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
//Get the node I want to output
xmlNodePtr node = ...
//Create the node buffer and fill it with the node content
xmlBufferPtr nodeBuffer = xmlBufferCreate();
htmlNodeDump(nodeBuffer, doc, node);
...
这会很好地转储节点的 HTML 内容,但字符实体会转换为 UTF-8 字符 - 输入 HTML 中存在的唯一实体是引号,例如 ’
和‘
,当我写出节点的 HTML 内容时我希望保留它。
我浏览了与 HTML 解析和 HTML 树函数相关的 libxml 文档,但似乎找不到任何有关 HTML 实体的信息。我也不确定这是否是在解析或输出期间完成的。我确实尝试使用 xmlNodeGetContent()
简单地输出节点的内容,并且实体也已被相应的 UTF8 字符替换,这让我怀疑这是一个解析问题,但我不是当然。
最佳答案
事实证明,问题在于 libxml 在内部使用 UTF-8(在 xmlsoft 上的 Encodings Support 中进行了解释),它将所有 HTML 字符实体转换为 UTF-8 字符,因此在输出 HTML 时会将它们保留为转换后的 UTF-8 字符。
该解决方案也在 xmlsoft 的编码部分中的“默认支持的编码”下提供:
libxml2 has a set of default converters for the following encodings (located in encoding.c):
- UTF-8 is supported by default (null handlers)
- UTF-16, both little and big endian
- ISO-Latin-1 (ISO-8859-1) covering most western languages
- ASCII, useful mostly for saving
- HTML, a specific handler for the conversion of UTF-8 to ASCII with HTML predefined entities like © for the Copyright sign.
它还建议使用转换函数'如 UTF8Toisolat1
'将从 libxml 函数返回的值转换为另一种编码。
解决方案是使用 UTF8ToHtml()
转换 HTML 输出函数将用相关的 HTML 实体替换非 ASCII 字符(例如 ’
或 ‘
)。这似乎留下了 HTML 标签 <
和>
字符未受影响,与我尝试使用 htmlEncodeEntities()
时不同,将它们替换为 <
和>
.
使用UTF8ToHtml()
时我没有解决的一件事是如何确定为输出缓冲区分配多少内存,因为用实体替换单个字符会增加 HTML 字符串的长度,因此您不能只使用输入 HTML 的长度。我只是分配了输入缓冲区大小的两倍(我想这应该足以满足我的所有用例),然后使用实际使用的长度(通过 UTF8ToHtml()
中的指针参数返回),但我不确定是否有更好的方法来做到这一点。
关于html-entities - 使用 libxml 保留 HTML 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10062780/