You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>是空的,所以问题大概率出在:

  1. 压缩的单行代码导致解析器误判:所有代码挤在一行,解析器可能把某些字符或FreeMarker指令的输出误识别为HTML标签
  2. 动态内容/引入模板的非法嵌套:比如<body>里有你没贴出来的<#include>模板,或者动态变量输出了带<p>的富文本
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:22:15