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

如何用XSLT区分XML自闭合<hello/>与空内容<hello></hello>标签?

区分XML自闭合标签与空内容标签的XSLT解决方案

首先得给你提个醒:在标准XML的语义里,<hello/>和<hello></hello>是完全等价的——XML解析器会把它们转换成完全相同的元素节点(没有任何子节点),所以纯标准的XSLT没办法直接区分这两种语法写法。但既然客户有明确的需求,我们还是有办法实现的,下面分两种场景给你解决方案:

场景1:严格区分语法写法(必须识别自闭合标签的写法)

这种情况需要绕开标准的XML节点解析,直接处理原始的XML文本,或者借助XSLT处理器的扩展能力:

方案A:用XSLT 3.0处理原始XML文本

通过unparsed-text读取原始XML文件,再用正则表达式匹配不同的标签写法。注意:这种方法只适合简单的XML结构,如果标签有属性、嵌套结构,正则很容易失效。

示例代码:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8"/>

  <xsl:template match="/">
    <!-- 读取原始XML文本 -->
    <xsl:variable name="raw-xml" select="unparsed-text('your-input.xml')"/>
    
    <!-- 匹配hello标签的两种写法 -->
    <xsl:analyze-string select="$raw-xml" regex="&lt;hello(/?)&gt;(?:&lt;/hello&gt;)?" flags="i">
      <xsl:matching-substring>
        <xsl:choose>
          <!-- 匹配自闭合标签 -->
          <xsl:when test="regex-group(1) = '/'">
            "hello": null
          </xsl:when>
          <!-- 匹配空内容的开始/结束标签 -->
          <xsl:otherwise>
            "hello": ""
          </xsl:otherwise>
        </xsl:choose>
      </xsl:matching-substring>
      <!-- 处理XML中的其他内容,这里省略 -->
    </xsl:analyze-string>
  </xsl:template>
</xsl:stylesheet>

方案B:借助处理器扩展(比如Saxon)

一些XSLT处理器(比如Saxon)支持扩展功能,可以序列化节点并控制输出格式,或者获取节点的原始语法信息。比如用XSLT 3.0的标准serialize函数,强制序列化时保留原始的标签形式(需要处理器支持相关参数):

示例代码:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8"/>

  <xsl:template match="hello">
    <!-- 序列化当前节点,关闭自动缩进,强制保留空元素的写法 -->
    <xsl:variable name="serialized-node" select="serialize(., map{
      'method': 'xml',
      'indent': false(),
      'omit-xml-declaration': true(),
      'use-empty-elements': false() <!-- 这个参数强制输出<hello></hello>而非自闭合 -->
    })"/>
    
    <xsl:choose>
      <!-- 如果序列化结果是自闭合标签(说明原节点是自闭合写法) -->
      <xsl:when test="$serialized-node = '&lt;hello/&gt;'">
        "hello": null
      </xsl:when>
      <xsl:otherwise>
        "hello": ""
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

注意:use-empty-elements参数的支持取决于处理器,部分处理器可能需要调整参数名称。

场景2:退而求其次——区分“无内容”与“空文本内容”

如果客户可以接受稍微调整需求(比如把<hello></hello>理解为包含空文本节点的元素),可以通过判断元素是否有子节点来实现:

示例代码:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8"/>

  <xsl:template match="hello">
    <xsl:choose>
      <!-- 没有任何子节点(对应自闭合标签,或无空白的<hello></hello>) -->
      <xsl:when test="not(node())">
        "hello": null
      </xsl:when>
      <!-- 有子节点但内容为空(比如包含空白的<hello></hello>) -->
      <xsl:when test="normalize-space(.) = ''">
        "hello": ""
      </xsl:when>
      <!-- 有实际内容的情况 -->
      <xsl:otherwise>
        "hello": "<xsl:value-of select="."/>"
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

这种方法的前提是:你的XML解析器会保留<hello></hello>中的空文本节点(可以通过xsl:preserve-space或解析器配置控制)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:37:38