C# XML转PDF实战教程 使用iTextSharp解析XML生成文档

9次阅读

itextsharp不直接支持xmlpdf,因其是pdf生成库而非xml渲染引擎,需手动解析xml并映射样式布局,或使用已废弃的xmlworker(需配字体、xhtml规范、避免大文件)。

C# XML转PDF实战教程 使用iTextSharp解析XML生成文档

为什么 iTextSharp 不直接支持 XML 转 PDF

iTextSharp 是一个 PDF 生成库,不是 XML 渲染引擎。它不解析 HTML 或 XML 标签语义,也不会自动把 <p></p> 变成段落、<h1></h1> 变成大标题。你传给它的 XML 字符串,它只会当纯文本处理——除非你自己写逻辑去遍历节点、映射样式、计算布局。

常见错误现象:document.Add(new Paragraph(xmlString)) 结果 PDF 里全是未解析的尖括号标签;或者用 XMLWorkerHelper.ParseXHtml() 却报 NULLReferenceException,因为没配好字体或 CSS。

  • 必须手动加载字体(尤其是中文),否则 XMLWorker 渲染时会静默失败
  • XMLWorker 已在 iTextSharp 5.x 后期被标记为废弃,官方不推荐新项目使用
  • XML 必须是格式良好(well-formed)的 XHTML 片段,不能含自定义标签或命名空间

XMLWorker 渲染简单 XHTML 的最小可行步骤

如果你只是要把一份结构清晰、不含 js/CSS 复杂逻辑的 XHTML 转 PDF(比如后台导出报表页),可以走 XMLWorker 这条路,但得踩准几个点:

  • 引用 iTextSharp.xmlworker NuGet 包(注意版本需与 iTextSharp 5.5.x 匹配)
  • 创建 FontFactory.RegisterDirectory() 或显式注册中文字体文件(如 "simhei.ttf"),否则中文全空白
  • CssFilesImpl 加载基础 CSS,至少定义 body { font-family: "SimHei" }
  • 调用 XMLWorkerHelper.ParseXHtml(writer, document, new StringReader(xhtml), null, Encoding.UTF8, fontProvider)

示例关键片段:

var fontProvider = new XMLWorkerFontProvider("fonts/simhei.ttf"); var css = @"body { font-family: 'SimHei'; font-size: 12px; }             h1 { color: #333; }"; var cssBytes = Encoding.UTF8.GetBytes(css); using (var ms = new MemoryStream(cssBytes)) {     XMLWorkerHelper.GetInstance().ParseXHtml(writer, document,         new StringReader(xhtml), ms, Encoding.UTF8, fontProvider); }

XmlDocument + 手动遍历比 XMLWorker 更可控

当你 XML 里有业务定制标签(比如 <invoice-number></invoice-number><payment-due></payment-due>),或者需要动态插入表格、页眉页脚、水印时,硬套 XMLWorker 反而绕远路。直接用 XmlDocument 解析,再按节点类型调用 document.Add() 对应元素更稳。

  • <title></title>new Paragraph(text).SetAlignment(Element.ALIGN_CENTER)
  • <table rows="3"> → 实例化 <code>PdfPTable(3),逐行添加 PdfPCell
  • <image src="logo.png"></image> → 用 iTextSharp.text.Image.GetInstance(path),注意路径必须是服务端可读的绝对路径
  • 避免在循环中反复调用 document.NewPage(),容易导致空白页——检查是否误在根节点外触发了分页
  • 生成速度慢、内存溢出?别让 XMLWorker 做它不该做的事

    大 XML(>2MB)+ 复杂 CSS + 多字体嵌入,会让 XMLWorker 在解析阶段就卡住或抛 OutOfMemoryException。这不是配置问题,是设计边界。

    • 单次渲染不要超过 500 行 XHTML;超长内容拆成多个 document 实例分批写入
    • 禁用 XMLWorker 的 CSS 解析(传 null 替代 CssFilesImpl),改用内联 style 控制基础样式
    • 字体只注册实际用到的字重(比如只要常规体,就别把 bold/italic 全塞进去)
    • 调试时加 try/catch 捕获 DocumentException,里面常含真实失败原因,比如 “Could not resolve font ‘SimHei’”

    真正难的不是怎么转,是怎么界定 XML 的职责边界:它该是数据容器,不是排版指令集。一旦开始往 XML 里塞 margin-top="20px"font-size="14pt",你就已经站在了维护地狱门口。

text=ZqhQzanResources