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

如何用XSLT 3.0压缩外部HTML文档输出的空白?

问题概述

用Apache FOP 2.8搭配支持XSLT 3.0的SaxonHE 12处理器,现有XSLT模板能把外部HTML的body内容嵌入输出,但输出存在大量冗余空白。尝试用normalize-space()处理document()获取的节点时,仅得到文本内容的拼接,无法生成保留HTML结构的压缩输出。

原XSLT模板:

<xsl:stylesheet version="1.0"
                xmlns:fopi="http://xmlgraphics.apache.org/fop/intermediate"
                xmlns:nav="http://xmlgraphics.apache.org/fop/intermediate/document-navigation"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xlink="http://www.w3.org/1999/xlink"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                xmlns:html="http://www.w3.org/TR/REC-html40">

<xsl:output method="html"
            version="4.0"
            encoding="utf-8"
            indent="no"/>
            
    <xsl:template name="embed-html">
      <xsl:param name="path"/>

      <xsl:copy-of select="document($path)/html:html/html:body/*"/>

    </xsl:template>

</xsl:stylesheet>

外部HTML示例(含冗余空白):

<html
  xmlns:v="urn:schemas-microsoft-com:vml"
  xmlns:o="urn:schemas-microsoft-com:office:office"
  xmlns:x="urn:schemas-microsoft-com:office:excel"
  xmlns="http://www.w3.org/TR/REC-html40">
  <head>
    <style>
    </style>
  </head>
  <body>
    <table>
      <tr>
        <th>Company</th>
        <th>Contact</th>
        <th>Country</th>
      </tr>
      <tr>
        <td>Alfreds Futterkiste</td>
        <td>Maria Anders</td>
        <td>Germany</td>
      </tr>
      <tr>
        <td
          height="24"
          class="x64"
          width="115"
          style="height: 18pt; width: 86.25pt">
          <a><span 
            style="font-size: 7pt;      
            color: #000000;"/>
          </a>
        </td>
        <td>Francisco Chang</td>
        <td>Mexico</td>
      </tr>
    </table>
  </body>
</html>

之前尝试的错误写法(仅生成文本拼接):

<xsl:template name="embed-html">
  <xsl:param name="path"/>

  <xsl:copy-of select="normalize-space(document($path)/html/body/*)"/>

</xsl:template>
解决方案

问题出在normalize-space()直接作用于节点集时,会提取所有节点的文本内容并拼接成纯字符串,完全丢失HTML结构。要保留结构同时压缩空白,需要通过XSLT模板匹配处理节点树,过滤冗余空白文本节点,同时规范化必要的文本内容。

修改后的XSLT代码(基于XSLT 3.0特性):

<xsl:stylesheet version="3.0"
                xmlns:fopi="http://xmlgraphics.apache.org/fop/intermediate"
                xmlns:nav="http://xmlgraphics.apache.org/fop/intermediate/document-navigation"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xlink="http://www.w3.org/1999/xlink"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                xmlns:html="http://www.w3.org/TR/REC-html40">

<xsl:output method="html"
            version="4.0"
            encoding="utf-8"
            indent="no"/>

<!-- 通用模板:复制元素及属性,递归处理子节点 -->
<xsl:template match="*">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

<!-- 过滤纯空白文本节点,对非空白文本做空格规范化 -->
<xsl:template match="text()">
  <xsl:variable name="trimmed" select="normalize-space(.)"/>
  <xsl:if test="$trimmed != ''">
    <xsl:value-of select="$trimmed"/>
  </xsl:if>
</xsl:template>

<!-- 修改后的嵌入模板:用apply-templates触发空白处理逻辑 -->
<xsl:template name="embed-html">
  <xsl:param name="path"/>

  <xsl:apply-templates select="document($path)/html:html/html:body/*"/>
</xsl:template>

</xsl:stylesheet>

关键说明

  1. 将XSLT版本改为3.0,充分利用SaxonHE 12的原生支持;
  2. 新增元素模板:复制所有元素及其属性,递归处理子节点以保留完整HTML结构;
  3. 文本节点模板:过滤完全空白的文本节点,对有实际内容的文本做normalize-space(),去除首尾空白并合并中间连续空格;
  4. 嵌入模板改用xsl:apply-templates,让外部HTML的每个节点都经过空白处理逻辑,最终输出保留结构且无冗余空白的压缩HTML。

内容的提问来源于stack exchange,提问作者CrazyEight

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:19:58