一些特殊的角色被&​​#39;取代?'从html

时间:2015-07-21 08:36:09

标签: c# html itextsharp

我正在尝试使用itextsharp库从html文件生成pdf,但我有一个问题,当我将html转换为pdf时,html文件的某些特殊字符被替换为'?'标志。 (前€)

这是我的代码:

var elements = XMLWorkerHelper.ParseToElementList(html, null);
foreach (var element in elements)
{    
    document.Add(element);
}

XMLWorkerHelper是一类itextsharp库。 我只是希望我的pdf与我的html文件生成相同。

2 个答案:

答案 0 :(得分:1)

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

根据文档System.Text.Encoding.Default

  

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

进一步(强调我的):

  

不同的计算机可以使用不同的编码作为默认编码, 默认编码甚至可以在一台计算机上更改 。因此,从一台计算机流式传输到另一台计算机甚至在同一台计算机上不同时间检索的数据可能 翻译错误 。此外,默认属性 返回的编码使用最适合的回退将不受支持的字符映射到代码页支持的字符 。出于这两个原因,通常不推荐使用默认编码的 。为了确保正确解码编码的字节,您应该使用Unicode编码(例如UTF8Encoding或UnicodeEncoding)和前导码。另一种选择是使用更高级别的协议来确保使用相同的格式进行编码和解码。

因此,从上面你可以看到,如果文件中没有关于如何解释原始字节的信息,.Net将只使用本地code page来解释它们。真正有趣的是,如果您将代码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只是在没有信息的情况下使用系统默认值。

答案 1 :(得分:0)

p.parse(new StringReader(html));

这对我有用