XSLT模板异常排查:item提前渲染且i标签class丢失
问题分析与解决方案
错误原因总结
你的XSLT出现两个问题,根源如下:
1. item节点在ul前被渲染
- 你在
elem模板中使用的选择器*[not(elem|item)]|text()仅处理了非item的子元素和文本节点,但XSLT的默认模板会对未被显式处理的元素节点执行<xsl:apply-templates/>,而你的item有匹配的模板,导致这部分节点被提前触发渲染。 - 更关键的是,
item模板存在语法错误:错误地用</ul>闭合<li>,直接导致输出的HTML结构混乱,进一步加重了顺序问题。
2. 标签class属性丢失
你的通用模板中,使用<xsl:copy>复制元素时,虽然写了<xsl:apply-templates select="node()|@*"/>,但XSLT默认没有处理属性的模板,因此元素的属性不会被复制,最终导致class丢失。
修正后的XSLT样式表
<?xml version='1.0'?> <xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> <xsl:output method="html" encoding="UTF-8" indent="yes"/> <!-- 处理根节点doc,生成外层有序列表 --> <xsl:template match='doc'> <ol> <xsl:apply-templates select='elem'/> </ol> </xsl:template> <!-- 处理elem节点,生成有序列表项,包含文本内容和嵌套的无序列表 --> <xsl:template match='elem'> <li> <!-- 仅处理elem下非item的所有节点(文本+其他元素) --> <xsl:apply-templates select='node()[not(self::item)]'/> <ul> <!-- 仅在此处处理item节点,确保嵌套在ul内 --> <xsl:apply-templates select='item'/> </ul> </li> </xsl:template> <!-- 处理item节点,生成无序列表项,修正闭合标签错误 --> <xsl:template match='item'> <li> <xsl:apply-templates/> </li> </xsl:template> <!-- 复制非elem/item的元素节点,并保留所有属性 --> <xsl:template match="*[not(self::elem|self::item)]"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <!-- 直接复制文本节点 --> <xsl:template match="text()"> <xsl:copy/> </xsl:template> </xsl:stylesheet>
修正说明
- 调整
elem模板的节点选择器为node()[not(self::item)],确保只处理非item的节点,避免默认模板提前触发item渲染。 - 修复
item模板的语法错误,将错误的</ul>替换为</li>,保证HTML结构的正确性。 - 修改通用元素模板,使用
<xsl:copy-of select="@*"/>直接复制元素的所有属性,解决class丢失问题。 - 拆分文本节点的处理模板,让逻辑更清晰,避免不必要的节点匹配冲突。
使用上述修正后的样式表,转换结果将完全符合你期望的HTML结构:
<ol> <li> Some text, <i class="i">including HTML markup</i> <ul> <li>Some more text, <i>including HTML markup</i></li> <li>Yet more text, <i>including HTML markup</i></li> </ul> </li> </ol>
内容的提问来源于stack exchange,提问作者user1636349
相关产品推荐
相关产品推荐

