如何使用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-'.,/@&()!+</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
相关产品推荐
相关产品推荐

