一些特殊字符用'?'同时从html生成PDF

本文关键字:html 生成 PDF 特殊字符 | 更新日期: 2023-09-27 18:03:57

我试图使用itextsharp库从html文件生成pdf,但我有一个问题,当我将html转换为pdf时,html文件的一些特殊字符被替换为'?的迹象。(例€)

下面是我的代码:
var elements = XMLWorkerHelper.ParseToElementList(html, null);
foreach (var element in elements)
{    
    document.Add(element);
}

XMLWorkerHelper是itextsharp库的一个类。我只是想让我的pdf文件和我的html文件一样

一些特殊字符用'?'同时从html生成PDF

如果你使用XMLWorkerHelper.ParseToElementList(String, String)(你是),那么iTextSharp将要求。net运行时通过调用System.Text.Encoding.Default.GetBytes()来找出文件的内容。

根据文档,System.Text.Encoding.Default

获取操作系统当前ANSI代码页的编码

进一步(强调我的):

不同的计算机可以使用不同的编码作为默认编码,并且默认编码甚至可以在单个计算机上更改。因此,从一台计算机到另一台计算机的数据流,甚至在同一台计算机上不同时间检索的数据都可能被错误地翻译为。此外,默认属性返回的编码使用最佳回退将不支持的字符映射到代码页支持的字符。由于这两个原因,通常不推荐使用默认编码的。为了确保编码的字节被正确解码,您应该使用Unicode编码,例如UTF8Encoding或UnicodeEncoding,并带有序言。另一种选择是使用更高级的协议来确保编码和解码使用相同的格式。

因此,从上面您将看到,在文件中没有关于如何解释原始字节的任何信息的情况下,. net将只使用本地代码页来解释它们。真正有趣的是,如果您将代码100%原样移动到另一台机器上,您可能会得到不同的结果,因为那台机器可能有不同的代码页集。

最好的解决方案是完全避免代码页。要做到这一点,只需将文件保存为Unicode兼容格式,如UTF8,并包含一个BOM来显式声明您的意图。BOM是可选的(有些人不赞成),但在没有其他信息(如HTTP标头或便利贴)的情况下,它也是最显式的方式。

第二个选择是用适当的编码重新实现XMLWorkerHelper.ParseToElementList()。SourceForge现在显然已经关闭了,下面是该方法的主体:

/**
 * Parses an HTML string and a string containing CSS into a list of Element objects.
 * The FontProvider will be obtained from iText's FontFactory object.
 * 
 * @param   html    a String containing an XHTML snippet
 * @param   css     a String containing CSS
 * @return  an ElementList instance
 */
public static ElementList ParseToElementList(String html, String css) {
    // CSS
    ICSSResolver cssResolver = new StyleAttrCSSResolver();
    if (css != null) {
        ICssFile cssFile = XMLWorkerHelper.GetCSS(new MemoryStream(Encoding.Default.GetBytes(css)));
        cssResolver.AddCss(cssFile);
    }
    // HTML
    CssAppliers cssAppliers = new CssAppliersImpl(FontFactory.FontImp);
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
    htmlContext.AutoBookmark(false);
    // Pipelines
    ElementList elements = new ElementList();
    ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
    HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, end);
    CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
    // XML Worker
    XMLWorker worker = new XMLWorker(cssPipeline, true);
    XMLParser p = new XMLParser(worker);
    p.Parse(new MemoryStream(Encoding.Default.GetBytes(html)));
    return elements;
}

p.Parse开头的倒数第二行代码是您想要更改的。因为我们不知道你文件的字节数(显然你的电脑也不知道),所以我们不能告诉你该把编码器切换到什么。

总结一下,这实际上根本不是iTextSharp问题,这实际上是。net运行时的默认行为。在没有信息的情况下,iTextSharp只是使用系统默认值

解析(新StringReader (html));