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

XSLT中如何对<opt>子树内容去除首尾空格与换行?

问题:XSLT转换中去除标签内容首尾的空格与换行,保留内部格式

XML输入数据

<?xml version="1.0" ?>
<input>
  <record>
    <name>James Smith</name>
    <country>United Kingdom</country>
    <opt>
      good social skills,
      <qualification>MSc</qualification>,
      10 years of experience
    </opt>
    <section>1B</section>
  </record>
  <record>
    <name>Rafael Pérez</name>
    <country>Spain</country>
    <section>2A</section>
  </record>
  <record>
    <name>Marie-Claire Legrand</name>
    <country>France</country>
    <opt>
      clear voice,
      <qualification>MBA</qualification>,
      3 years of experience
    </opt>
    <section>1B</section>
  </record>

</input>

现有XSLT代码

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text" indent="yes" encoding="utf-8"/>

  <xsl:template match="input">
    <xsl:text>------------------------------------------&#xa;</xsl:text>
    <xsl:for-each select="record">
      <xsl:apply-templates 
        select="node()[not(self::text()[not(normalize-space())])]"/>
      <xsl:text>&#xa;------------------------------------------&#xa;</xsl:text>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="qualification">
    <xsl:choose>
      <xsl:when test=". = 'MBA'">Master in Business Administration</xsl:when>
      <xsl:when test=". = 'MSc'">Master in Sciences</xsl:when>
      <xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="name|country">
    <xsl:value-of select="."/>
    <xsl:text>, </xsl:text>
  </xsl:template>

  <xsl:template match="section">
    <xsl:text>Section: </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>.</xsl:text>
  </xsl:template>

  <xsl:template match="opt">
    <xsl:text>(</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>), </xsl:text>
  </xsl:template>

</xsl:stylesheet>

当前输出结果

------------------------------------------
James Smith, United Kingdom, (
      good social skills,
      Master in Sciences,
      10 years of experience
    ), Section: 1B.
------------------------------------------
Rafael Pérez, Spain, Section: 2A.
------------------------------------------
Marie-Claire Legrand, France, (
      clear voice,
      Master in Business Administration,
      3 years of experience
    ), Section: 1B.
------------------------------------------

期望输出结果

------------------------------------------
James Smith, United Kingdom, (good social skills,
      Master in Sciences,
      10 years of experience), Section: 1B.
------------------------------------------
Rafael Pérez, Spain, Section: 2A.
------------------------------------------
Marie-Claire Legrand, France, (clear voice, 
      Master in Business Administration, 
      3 years of experience), Section: 1B.
------------------------------------------

解决方案

问题出在<opt>标签下的首尾文本节点包含多余的换行和空格,我们需要针对性处理这些文本节点,同时保留内部的格式和标签转换逻辑。

修改后的XSLT代码如下(核心修改为<opt>模板及新增的文本节点处理模板):

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text" indent="yes" encoding="utf-8"/>

  <xsl:template match="input">
    <xsl:text>------------------------------------------&#xa;</xsl:text>
    <xsl:for-each select="record">
      <xsl:apply-templates 
        select="node()[not(self::text()[not(normalize-space())])]"/>
      <xsl:text>&#xa;------------------------------------------&#xa;</xsl:text>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="qualification">
    <xsl:choose>
      <xsl:when test=". = 'MBA'">Master in Business Administration</xsl:when>
      <xsl:when test=". = 'MSc'">Master in Sciences</xsl:when>
      <xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="name|country">
    <xsl:value-of select="."/>
    <xsl:text>, </xsl:text>
  </xsl:template>

  <xsl:template match="section">
    <xsl:text>Section: </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>.</xsl:text>
  </xsl:template>

  <!-- 修改opt模板,分节点处理首尾空白 -->
  <xsl:template match="opt">
    <xsl:text>(</xsl:text>
    <!-- 处理第一个子节点,去除前导空白 -->
    <xsl:apply-templates select="node()[1]" mode="trim-start"/>
    <!-- 处理中间节点,保留原样 -->
    <xsl:apply-templates select="node()[position() > 1 and position() < last()]"/>
    <!-- 处理最后一个子节点,去除尾随空白 -->
    <xsl:apply-templates select="node()[last()]" mode="trim-end"/>
    <xsl:text>), </xsl:text>
  </xsl:template>

  <!-- 去除文本节点的前导空白 -->
  <xsl:template match="text()" mode="trim-start">
    <xsl:value-of select="substring(., string-length(substring-before(., normalize-space(.))) + 1)"/>
  </xsl:template>

  <!-- 去除文本节点的尾随空白 -->
  <xsl:template match="text()" mode="trim-end">
    <xsl:value-of select="substring(., 1, string-length(.) - string-length(substring-after(normalize-space(.), normalize-space(.))))"/>
  </xsl:template>

  <!-- 非文本节点在trim模式下直接应用原模板 -->
  <xsl:template match="*" mode="trim-start">
    <xsl:apply-templates select="."/>
  </xsl:template>

  <xsl:template match="*" mode="trim-end">
    <xsl:apply-templates select="."/>
  </xsl:template>

</xsl:stylesheet>

核心逻辑说明

  1. <opt>模板拆分处理:将子节点分为首节点、中间节点、尾节点分别处理,确保首尾节点的空白被清理,中间节点保留原有格式。
  2. trim-start模式:针对第一个文本节点,通过substring截取从第一个非空白字符开始的内容,去除前导的换行和空格。
  3. trim-end模式:针对最后一个文本节点,截取到最后一个非空白字符结束的内容,去除尾随的换行和空格。
  4. 非文本节点兼容:对于<qualification>这类标签节点,在trim模式下直接调用原模板完成替换,不影响原有逻辑。

内容的提问来源于stack exchange,提问作者Pierre François

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:50:41