XSLT 1.0中能否匹配跨多XML节点的模板?含IF块转换需求
可行,这是可以实现的解决方案
XSLT 1.0完全能处理这类嵌套代码块的转换,核心思路是递归匹配IFBEGIN节点,找到对应的IFEND节点,将中间的LINE节点嵌套到<IF>元素内,同时避免重复处理节点。
示例原XML
<CODE> <LINE> <OPERATOR>ASSIGN</OPERATOR> <VALUE>x=1</VALUE> </LINE> <LINE> <OPERATOR>IFBEGIN</OPERATOR> <CONDITION>x>0</CONDITION> </LINE> <LINE> <OPERATOR>PRINT</OPERATOR> <VALUE>"Positive"</VALUE> </LINE> <LINE> <OPERATOR>IFEND</OPERATOR> </LINE> <LINE> <OPERATOR>END</OPERATOR> </LINE> </CODE>
实现的XSLT 1.0代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <!-- 匹配根节点,启动处理 --> <xsl:template match="/CODE"> <CODE> <xsl:apply-templates select="LINE[1]" mode="process"/> </CODE> </xsl:template> <!-- 处理普通LINE节点(非IFBEGIN/IFEND) --> <xsl:template match="LINE" mode="process"> <xsl:element name="{OPERATOR}"> <xsl:copy-of select="*[not(local-name()='OPERATOR')]"/> </xsl:element> <!-- 处理下一个节点 --> <xsl:apply-templates select="following-sibling::LINE[1]" mode="process"/> </xsl:template> <!-- 处理IFBEGIN节点,构建IF块 --> <xsl:template match="LINE[OPERATOR='IFBEGIN']" mode="process"> <IF> <xsl:copy-of select="CONDITION"/> <!-- 递归处理IFBEGIN到对应IFEND之间的所有节点 --> <xsl:apply-templates select="following-sibling::LINE[1]" mode="inside-if"> <xsl:with-param name="end-pos" select="count(following-sibling::LINE[OPERATOR='IFEND'][1]/preceding-sibling::LINE) + 1"/> </xsl:apply-templates> </IF> <!-- 跳过IFEND及之前的节点,处理后续内容 --> <xsl:apply-templates select="following-sibling::LINE[OPERATOR='IFEND'][1]/following-sibling::LINE[1]" mode="process"/> </xsl:template> <!-- 处理IF块内部的节点,直到遇到对应IFEND --> <xsl:template match="LINE" mode="inside-if"> <xsl:param name="end-pos"/> <xsl:if test="count(preceding-sibling::LINE) + 1 < $end-pos"> <xsl:element name="{OPERATOR}"> <xsl:copy-of select="*[not(local-name()='OPERATOR')]"/> </xsl:element> <xsl:apply-templates select="following-sibling::LINE[1]" mode="inside-if"> <xsl:with-param name="end-pos" select="$end-pos"/> </xsl:apply-templates> </xsl:if> </xsl:template> <!-- 忽略IFEND节点,避免重复处理 --> <xsl:template match="LINE[OPERATOR='IFEND']" mode="process"/> </xsl:stylesheet>
转换后的结果
<CODE> <ASSIGN> <VALUE>x=1</VALUE> </ASSIGN> <IF> <CONDITION>x>0</CONDITION> <PRINT> <VALUE>"Positive"</VALUE> </PRINT> </IF> <END/> </CODE>
关键逻辑说明
- 使用带mode的模板区分普通节点处理和IF块内部处理,避免节点重复匹配。
- 处理IFBEGIN时,先定位到对应的IFEND节点位置,递归处理中间所有LINE节点并嵌套到
<IF>元素内。 - 处理完IF块后,直接跳转到IFEND的下一个节点继续处理,跳过IFBEGIN到IFEND之间的节点,防止重复转换。
内容的提问来源于stack exchange,提问作者user2850751
相关产品推荐
相关产品推荐

