尝试解析 html 以进行 pdf 转换时出现 ItextSharp 错误

Posted

技术标签:

【中文标题】尝试解析 html 以进行 pdf 转换时出现 ItextSharp 错误【英文标题】:ItextSharp Error on trying to parse html for pdf conversion 【发布时间】:2012-08-20 06:07:55 【问题描述】:

我使用 ItextSharp 模块将下面列出的 html 转换为 pdf 页面。

        <div style="font-size: 18pt; font-weight: bold;">
    mma<br>mmar</div><br> <br>
    <div style="font-size: 14pt;">Click to View Pricing
    </div>
    <br>
    <div>
    <table>
    <tr><td> <a href="http://www.mma.com/fci" style="color: Blue; font-size: 10pt; text-decoration: underline;"> FCI</a>:</td> 
<td><a href="http://www.mma.com/access/?pn=78211-014" style="color: Blue; font-size: 10pt; text-decoration: underline;"> 78211-014</a></td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-009" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-009</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-006" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-006</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-007" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-007</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-003" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-003</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-005" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-005</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-008"
 style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-008</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-004" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-004</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-012" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-012</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-007LF" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-007LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-015LF" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-015LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-003LF"
 style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-003LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-009LF" 
style="color: Blue; font-size: 10pt; text-decoration:
underline;">78211-009LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-005LF" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-005LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-010LF" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-010LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-006LF"
 style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-006LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-014LF"
 style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-014LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-004LF" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-004LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-012LF"
 style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-012LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-008LF"
 style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-008LF</td></tr><tr><td></td> <td>
<a href="http://www.mma.com/access/?pn=78211-011LF" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-011LF</td></tr><tr><td></td> <td><a href="http://www.mma.com/access/?pn=78211-013LF" 
style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-013LF</td></tr><tr><td></td> <td><a href="http://www.mma.com/access/?pn=78211-010" style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-010</td></tr><tr><td></td>
<td><a href="http://www.mma.com/access/?pn=78211-015"
 style="color: Blue; font-size: 10pt; text-decoration: underline;">78211-015</td></tr><tr><td> 
<a href="http://www.mma.com/souriau" 
style="color: Blue; font-size: 10pt; text-decoration: underline;"> Souriau</a>:</td>
 <td><a href="http://www.mma.com/access/?pn=24JR124-3" style="color: Blue; font-size: 10pt; text-decoration: underline;"> 24JR124-3</a></td></tr></table></div>

生成上述html的C#代码:

 var html = new StringBuilder(@"<div style=""font-size: 18pt; font-weight: bold;"">Authorized Distributor</div><br> <br><div style=""font-size: 14pt;"">Click to View Pricing, Inventory, Delivery & Lifecycle Information:</div><br>");
            List<MfrBrandView> mfrBrands = MfrBrandView.Load(fileId);
            var uniquesuppliers = mfrBrands.GroupBy(t => new t.Manufacturer,t.SupplierVirtualDirectory).Select(g => g.First());
            html.Append("<div><table>");
            foreach (var uniquesupplier in uniquesuppliers)
            
                var mfrPartNums =
                    mfrBrands.Where(t => t.ManufacturerId == uniquesupplier.ManufacturerId).Select(
                        t => t.ManufacturerPartNumber).ToList();
                html.AppendFormat(@"<tr><td> <a href=""http://www.mma.com/0"" style=""color: Blue; font-size: 10pt; text-decoration: underline;""> 1</a>:</td> <td><a href=""http://www.mma.com/access/?pn=2"" style=""color: Blue; font-size: 10pt; text-decoration: underline;""> 2</a></td></tr>", uniquesupplier.SupplierVirtualDirectory, uniquesupplier.MouserizationLabel, mfrPartNums[0]);

                for (int i = 1; i < mfrPartNums.Count(); i++)
                
                    html.AppendFormat(
                        @"<tr><td></td> <td><a href=""http://www.mma.com/access/?pn=0"" style=""color: Blue; font-size: 10pt; text-decoration: underline;"">0</td></tr>",
                        mfrPartNums[i]);
                
            
            html.Append("</table></div>");
            return html.ToString();

html形成后生成页面的代码:

PdfWriter writer = null;
            PdfDocument doc = null;
            //PdfReader reader = new PdfReader(content);
           // reader.Info["Title"]

            try
            
                doc = new PdfDocument();
                doc.SetPageSize(PageSize.LETTER);
                writer = PdfWriter.GetInstance(doc, content);
                writer.CloseStream = false;
                doc.Open();
                doc.NewPage();

                foreach (IElement element in iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(new StringReader(html), null))
                
                    doc.Add(element);
                
            

下面是我得到一个异常的地方,说 “无法投射类型的对象 'iTextSharp.text.html.simpleparser.CellWrapper' 到输入'iTextSharp.text.Paragraph'。” iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(new StringReader(html), null)

我试图解析的 html 有问题吗?有没有更好的方法来做到这一点? 非常感谢您的帮助。非常感谢。

【问题讨论】:

你能给我们看一下 C# 代码吗?您正在尝试将单元格设为段落。只是太高了一级。 嗯..我猜这是 ItextSharp Parser 正在尝试这样做。我不知道在尝试使用 Itextsharp 将 html 转换为 PDF 时是否不允许某些 html 元素 Itextsharp 不喜欢我将 标签放在 标签内。看起来这就是问题所在。 是的....但不是我想象的那样。我必须将每个 标签放在 中。并且不得不在我希望在页面上的格式方面做出一些妥协,因为我无法根据需要在表格中排列所有 标记。 【参考方案1】:

这是你需要做的步骤

1- 从 nuget 安装 itextsharp 和 XMLWorker

2-然后将您的设计放入带有内联 CSS 的 html(此处为 Invoice.html)中

3-确保所有标签都像断点或td一样正确结束(这里我之前遇到错误)

4-这里的图片不会在本地显示,所以为了不浪费时间,我将图片上传到服务器并提供服务器路径来访问 Image.U 可以研究更多以在本地运行它。

Document doc = new Document();

PdfPTable tableLayout = new PdfPTable(4);

PdfWriter writer= PdfWriter.GetInstance(doc, new FileStream(Server.MapPath("~/Admin/T13.pdf"), FileMode.Create));                 

doc.Open();

string contents = File.ReadAllText(Server.MapPath("~/Admin/invoice.html"));

StringReader sr = new StringReader(contents);


XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, sr);  

doc.Close();

【讨论】:

【参考方案2】:

`HTMLWorker' has been deprecated 支持 XMLWorker。这是一个使用上面使用的 HTML 的 sn-p 测试的工作示例:

StringReader html = new StringReader(@"
<div style='font-size: 18pt; font-weight: bold;'>
Mouser Electronics <br />Authorized Distributor</div><br /> <br />
<div style='font-size: 14pt;'>Click to View Pricing, Inventory, Delivery & Lifecycle Information:
</div>
<br />
<div>
<table>
<tr><td></td><td>
<a href='http://www.mouser.com/access/?pn=78211-009' 
style='color: Blue; font-size: 10pt; text-decoration: underline;'>78211-009</a></td></tr>
</table></div>    
");      
using (Document document = new Document()) 
  PdfWriter writer = PdfWriter.GetInstance(document, STREAM);
  document.Open();
  XMLWorkerHelper.GetInstance().ParseXHtml(
    writer, document, html
  );

当使用XMLWorker 时,您需要使用格式良好的 HTML - 毕竟它是一个 XML 解析器。上述问题中的示例HTML 没有关闭&lt;a&gt;&lt;br&gt; 标签。像HtmlAgilityPack 这样的HTML 解析器将解决这些问题,并转为:

<div><img src='a.gif'><br><hr></div>

进入这个:

<div><img src='a.gif' /><br /><hr /></div>

只有几行代码:

var hDocument = new HtmlDocument()

    OptionWriteEmptyNodes = true,
    OptionAutoCloseOnEnd = true
;
hDocument.LoadHtml("<div><img src='a.gif'><br><hr></div>");
var closedTags  = hDocument.DocumentNode.WriteTo();

XMLWorker 是available as a nuget package,或as a separate download at sourceforge。

见here for more advanced usage 或XMLWorker

【讨论】:

谢谢...这是一个很好的答案!我们现在不想改变使用 ITextsharp。项目太远了,无法做到这一点。 是否有有效的解决方法?我正在做一行一行的html来做这件事……基本上把所有的“链接”放在div标签中。这改变了文件的最初计划格式。 XMLWorker 是一个单独的下载,但它IS与 iTextSharp 一起使用。因此,您可以使用原始格式(&lt;table&gt; 标签)而不是像上面提供的示例代码那样将超链接包装在 &lt;div&gt; 标签中。我不确定您使用有效的解决方法是什么意思-如果您查看我上面从 iText 邮件列表中引用的第一个链接,它会提到在 4.xx 分支或 5.xx 分支的某个地方表格单元格中的超链接已损坏,并且 iText 开发团队没有计划对 HTMLWorker 进行进一步开发。 抱歉误会你了!我以为你在谈论一个完全不同的工具。我明白你在说什么。 此代码成功运行,但土耳其语字符未显示在 PDF 文档中。如何设置此代码的编码?【参考方案3】:

试试下面的代码

    &lt;a href="http://www.abcd.com"&gt;&lt;/a&gt;

这里我们将 &lt;和 > 与&amp;gt;所以我变成了&amp;lt;a&amp;gt;,变成了&amp;lt;/a&amp;gt;

【讨论】:

以上是关于尝试解析 html 以进行 pdf 转换时出现 ItextSharp 错误的主要内容,如果未能解决你的问题,请参考以下文章

将 pdf 转换为图像时出现 Ghostscript 错误

如果source是pdf类型,则将ps转换为pdf时出现问题

使用 ImageMagick 将 PNG 文件转换为 PDF 时出现粗糙的边缘

pdf转换成PPt时出现乱码,比如说就是那些希腊字母显示不出来等,该怎么办?

走目录时的字数PDF文件

如何解决利用aspose把word文档转换为pdf文档时出现乱码 C#