2012-04-08 99 views
2

我正在编写一个方法来解析HTML字符串,查询并获取一些节点,然后输出这些节点的HTML。使用libxml保留HTML实体

我使用的libxml ,并已成功地加载和解析输入HTML和输出,我想,但我想任何HTML实体保存,libxml的节点的HTML字符串似乎将这些到他们相关的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字符,这让我怀疑这是一个解析问题,但我不确定。

回答

3

事实证明,问题在于libxml在UTF-8内部工作(在xmlsoft上的Encodings Support中解释过),它会将所有HTML字符实体转换为UTF-8字符,因此在输出HTML时会将这些转换为转换UTF-8字符。

该溶液也呈现于上xmlsoft编码部分,下“默认支持的编码”:

libxml2的具有一组为以下编码默认转换器(位于encoding.c):

  1. UTF-8的默认支持(空处理程序)
  2. UTF-16,这两个小和大端
  3. ISO拉丁-1(ISO-8859-1)涵盖了大部分西方语言
  4. ASCII,有用的多为节约
  5. HTML,为UTF-8的转换为ASCII与像&复制HTML预定义的实体一个特别的处理;版权标志。

它还建议使用转换函数“等UTF8Toisolat1”转换值从libxml的功能到另一个编码返回。

解决方案是将HTML输出与UTF8ToHtml()函数进行转换,该函数将用它们相关的HTML实体(如&rsquo;&lsquo;)替换非ASCII字符。这似乎将HTML标记<>字符保持不变,这与我尝试使用htmlEncodeEntities()时不同,后者用&lt;&gt;替换它们。

使用UTF8ToHtml()时我没有解决的一件事是如何确定为输出缓冲区分配多少内存,因为用实体替换单个字符会增加HTML字符串的长度,所以不能使用输入HTML的长度。我简单地分配了两倍的输入缓冲区大小(我想应该足够用于所有的用例),然后使用实际使用的长度(通过UTF8ToHtml()中的指针参数返回),但我不确定是否有更好的方法来做到这一点。