NS高级PDF模板报错求助:<tr>子元素非<td>问题排查
解决NS高级PDF模板中
<tr>子元素非<td>的报错问题 我来帮你排查这个棘手的报错——虽然你贴的代码里看不到<tr>或<p>的问题,但这个错误提示其实指向了模板渲染时表格结构的非法嵌套,大概率是隐式的空白/动态内容导致的,以下是具体的解决思路和步骤:
问题回顾
你遇到的报错:
Error on line 13, column 142 in template. Detail... kid is
not : ignoring
尝试删除报错行、注释if语句、调整行位置都没用,说明问题不在你看到的<link>标签本身,而是模板解析或动态渲染时的隐性问题。你的模板代码如下:
<?xml version="1.0"?><!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd"> <pdf> <head> <link name="NotoSans" type="font" subtype="truetype" src="${nsfont.NotoSans_Regular}" src-bold="${nsfont.NotoSans_Bold}" src-italic="${nsfont.NotoSans_Italic}" src-bolditalic="${nsfont.NotoSans_BoldItalic}" bytes="2" /> <#if .locale == "zh_CN"> <link name="NotoSansCJKsc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKsc_Regular}" src-bold="${nsfont.NotoSansCJKsc_Bold}" bytes="2" /> <#elseif .locale == "zh_TW"> <link name="NotoSansCJKtc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKtc_Regular}" src-bold="${nsfont.NotoSansCJKtc_Bold}" bytes="2" /> <#elseif .locale == "ja_JP"> <link name="NotoSansCJKjp" type="font" subtype="opentype" src="${nsfont.NotoSansCJKjp_Regular}" src-bold="${nsfont.NotoSansCJKjp_Bold}" bytes="2" /> <#elseif .locale == "ko_KR"> <link name="NotoSansCJKkr" type="font" subtype="opentype" src="${nsfont.NotoSansCJKkr_Regular}" src-bold="${nsfont.NotoSansCJKkr_Bold}" bytes="2" /> <#elseif .locale == "th_TH"> <!-- in this line error appears --> <link name="NotoSansThai" type="font" subtype="opentype" src="${nsfont.NotoSansThai_Regular}" src-bold="${nsfont.NotoSansThai_Bold}" bytes="2" /> </#if> <style type="text/css">table { font-size: 9pt; table-layout: fixed; width: 100%; } th { font-weight: bold; font-size: 8pt; vertical-align: middle; padding: 5px 6px 3px; background-color: #e3e3e3; color: #333333; padding-bottom: 10px; padding-top: 10px; } td { padding: 4px 6px; } b { font-weight: bold; color: #333333; } </style> </head> <body> </body> </pdf>
核心原因分析
这个报错的意思是:PDF渲染引擎在解析<tr>标签时,发现它的直接子元素是<p>,而不是合法的<td>或<th>。但你贴的代码里<body>是空的,所以问题大概率出在:
- 压缩的单行代码导致解析器误判:所有代码挤在一行,解析器可能把某些字符或FreeMarker指令的输出误识别为HTML标签
- 动态内容/引入模板的非法嵌套:比如
<body>里有你没贴出来的<#include>模板,或者动态变量输出了带<p>的富文本 - FreeMarker空白字符被解析为文本节点:多余的换行/空格被渲染引擎自动包裹成
<p>标签
解决步骤
1. 先格式化代码,排除解析误判
把压缩的单行代码按XML规范换行缩进,这样能避免解析器的标签识别错误,也方便你排查问题:
<?xml version="1.0"?> <!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd"> <pdf> <head> <link name="NotoSans" type="font" subtype="truetype" src="${nsfont.NotoSans_Regular}" src-bold="${nsfont.NotoSans_Bold}" src-italic="${nsfont.NotoSans_Italic}" src-bolditalic="${nsfont.NotoSans_BoldItalic}" bytes="2" /> <#if .locale == "zh_CN"> <link name="NotoSansCJKsc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKsc_Regular}" src-bold="${nsfont.NotoSansCJKsc_Bold}" bytes="2" /> <#elseif .locale == "zh_TW"> <link name="NotoSansCJKtc" type="font" subtype="opentype" src="${nsfont.NotoSansCJKtc_Regular}" src-bold="${nsfont.NotoSansCJKtc_Bold}" bytes="2" /> <#elseif .locale == "ja_JP"> <link name="NotoSansCJKjp" type="font" subtype="opentype" src="${nsfont.NotoSansCJKjp_Regular}" src-bold="${nsfont.NotoSansCJKjp_Bold}" bytes="2" /> <#elseif .locale == "ko_KR"> <link name="NotoSansCJKkr" type="font" subtype="opentype" src="${nsfont.NotoSansCJKkr_Regular}" src-bold="${nsfont.NotoSansCJKkr_Bold}" bytes="2" /> <#elseif .locale == "th_TH"> <!-- 原报错行 --> <link name="NotoSansThai" type="font" subtype="opentype" src="${nsfont.NotoSansThai_Regular}" src-bold="${nsfont.NotoSansThai_Bold}" bytes="2" /> </#if> <style type="text/css"> table { font-size: 9pt; table-layout: fixed; width: 100%; } th { font-weight: bold; font-size: 8pt; vertical-align: middle; padding: 5px 6px 3px; background-color: #e3e3e3; color: #333333; padding-bottom: 10px; padding-top: 10px; } td { padding: 4px 6px; } b { font-weight: bold; color: #333333; } </style> </head> <body> <!-- 这里检查是否有动态内容或引入的模板 --> </body> </pdf>
2. 排查动态内容中的非法标签
如果<body>里有你没贴出来的内容,比如表格、<#include>指令或者动态变量,重点检查:
- 所有
<tr>的直接子元素是否只有<td>或<th>,有没有直接在<tr>下写文本或<p>标签 - 动态变量(比如
${content})是否输出了富文本,里面带<p>标签——如果是这种情况,需要把<p>替换成<td>或者去掉标签 - 引入的子模板是否有非法的表格嵌套
3. 处理FreeMarker的空白字符
FreeMarker默认会保留模板中的空白,这些空白在PDF渲染时可能被自动包裹成<p>标签。可以通过以下方式解决:
- 在模板开头添加全局空白设置:
<#setting strip_whitespace=true> - 在FreeMarker指令上添加
trim参数,比如:<#if .locale == "zh_CN" trim>
4. 用极简模板测试
把<body>替换成一个完全合法的简单表格,验证报错是否消失:
<body> <table> <tr> <th>测试表头</th> </tr> <tr> <td>测试内容</td> </tr> </table> </body>
如果这个测试模板不报错,说明问题肯定出在你原来的<body>内容里,逐步还原内容就能定位到具体的错误点。
内容的提问来源于stack exchange,提问作者Tenecious
相关产品推荐
相关产品推荐

