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

如何使用XSLT apply-template处理不同名称后代元素并选取首个有效值

XSLT多节点匹配问题解决方案

核心问题修正

你现有代码的两处错误如下:

  • 节点路径匹配错误:XML结构中Name节点嵌套在Info节点下,你写的Author/Name/FirstName路径缺少Info层级,无法命中任何节点
  • 选择节点范围不全:仅指定了FirstName作为应用模板的节点,自然不会触发LastName的匹配逻辑,需要同时选择两个元素

修改后的完整XSLT代码如下:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:variable name="allowed-start-chars">abcdefghijklmnopqrstuvwxyz</xsl:variable>
    <xsl:variable name="allowed-follow-chars">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ?abcdefghijklmnopqrstuvwxyz-&apos;.,/@&amp;()!+</xsl:variable>

    <xsl:template match="/">
        <html>
            <body>
                <div>
                    <!-- 按文档顺序选择两个元素,优先处理FirstName -->
                    <xsl:apply-templates select="Author/Info/Name/FirstName|Author/Info/Name/LastName"/>
                </div>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="FirstName|LastName">
        <!-- 找到符合开头要求的首个字符 -->
        <xsl:variable name="start-chars" select="translate(., translate(., $allowed-start-chars, ''), '')"/>
        <xsl:variable name="start-char" select="substring($start-chars, 1, 1)"/>
        <!-- 提取开头字符之后的文本 -->
        <xsl:variable name="tail" select="substring-after(., $start-char)"/>
        <!-- 清除后续文本中的非法字符 -->
        <xsl:variable name="fo" select="translate($tail, translate($tail, $allowed-follow-chars, ''), '')"/>        
        <xsl:choose>
            <!-- 仅输出清洗后非空的结果 -->
            <xsl:when test="string-length($start-char) > 0 and normalize-space(concat($start-char, $fo))">
                <xsl:value-of select="normalize-space(concat($start-char, $fo))"/>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

如果需要仅输出第一个有效的结果,不需要同时输出两个元素的清洗值,可以调整逻辑在匹配到第一个有效值后直接终止后续处理:

<xsl:template match="/">
    <html>
        <body>
            <div>
                <xsl:variable name="cleanFirst">
                    <xsl:apply-templates select="Author/Info/Name/FirstName"/>
                </xsl:variable>
                <xsl:choose>
                    <xsl:when test="normalize-space($cleanFirst) != ''">
                        <xsl:value-of select="$cleanFirst"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="Author/Info/Name/LastName"/>
                    </xsl:otherwise>
                </xsl:choose>
            </div>
        </body>
    </xsl:template>

性能说明

你使用的双translate字符过滤方法是XSLT 1.0环境下的标准实现,本身没有性能缺陷。常规业务场景下(单节点文本长度小于10万字符),Java内置的Xalan处理器对这类内置函数的优化足够支撑使用,不需要额外做性能调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 04:36:05