使用XSLT 1.0转换XML时的元素拆分与循环处理问题咨询
在XSLT 1.0中拆分输入元素到多个输出集合的实现
这问题我之前也帮人处理过,XSLT 1.0里确实没法像常规编程语言那样直接创建两个列表然后追加数据,但用**模板模式(mode)**结合节点遍历,就能完美实现你要的“把单个输入元素的信息分到两个输出元素,循环处理所有输入”的需求。
我先给你一个典型场景的示例,你可以直接套用到你的实际XML结构上:
示例输入XML
假设你的输入是每个<input>元素里包含两部分需要拆分到不同输出集合的信息:
<root> <input> <id>1</id> <partA>Apple</partA> <partB>Banana</partB> </input> <input> <id>2</id> <partA>Cherry</partA> <partB>Date</partB> </input> </root>
期望输出XML
你希望把所有partA放到<firstSet>,所有partB放到<secondSet>:
<output> <firstSet> <entry> <refId>1</refId> <content>Apple</content> </entry> <entry> <refId>2</refId> <content>Cherry</content> </entry> </firstSet> <secondSet> <entry> <refId>1</refId> <content>Banana</content> </entry> <entry> <refId>2</refId> <content>Date</content> </entry> </secondSet> </output>
XSLT 1.0实现代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 匹配根节点,搭建输出的整体结构 --> <xsl:template match="/root"> <output> <!-- 生成第一个集合:调用mode为first的模板处理所有input --> <firstSet> <xsl:apply-templates select="input" mode="first"/> </firstSet> <!-- 生成第二个集合:调用mode为second的模板处理所有input --> <secondSet> <xsl:apply-templates select="input" mode="second"/> </secondSet> </output> </xsl:template> <!-- 模板:处理input元素,提取partA生成firstSet的entry --> <xsl:template match="input" mode="first"> <entry> <refId><xsl:value-of select="id"/></refId> <content><xsl:value-of select="partA"/></content> </entry> </xsl:template> <!-- 模板:处理input元素,提取partB生成secondSet的entry --> <xsl:template match="input" mode="second"> <entry> <refId><xsl:value-of select="id"/></refId> <content><xsl:value-of select="partB"/></content> </entry> </xsl:template> </xsl:stylesheet>
核心思路解释
- **模板模式(mode)**是关键:它允许我们对同一个
<input>节点定义两种不同的转换逻辑,分别对应输出到两个集合的需求。 - 两次调用
<xsl:apply-templates>,分别指定不同的mode,就能遍历所有输入节点,把每个节点的不同部分提取到对应的输出集合里。
如果你的输入是分隔符形式的信息
要是你的输入元素是用分隔符(比如|)存储两部分内容,比如<item>Apple|Banana</item>,只需要调整模板里的提取逻辑,用substring-before和substring-after拆分内容:
<xsl:template match="item" mode="first"> <entry> <content><xsl:value-of select="substring-before(., '|')"/></content> </entry> </xsl:template> <xsl:template match="item" mode="second"> <entry> <content><xsl:value-of select="substring-after(., '|')"/></content> </entry> </xsl:template>
这种方式完全符合XSLT 1.0的规范,不需要额外扩展,也能高效处理你的需求。
内容的提问来源于stack exchange,提问作者PipperChip
相关产品推荐
相关产品推荐

