如何在XSLT 2.0中不使用for-each循环合并两个XML输入变量
问题描述
需要处理InputVar1.xml中的每个<employeeNumber>,从InputVar2.xml中获取对应的部门信息,生成指定格式的输出文件,仅保留InputVar1中存在的员工记录。要求使用XSLT 2.0实现,且不得使用for-each循环。
输入文件
InputVar1.xml
<Employees> <List> <employeeNumber>123</employeeNumber> <employeeName>abc</employeeName> </List> <List> <employeeNumber>453</employeeNumber> <employeeName>cde</employeeName> </List> <List> <employeeNumber>678</employeeNumber> <employeeName>efg</employeeName> </List> </Employees>
注:原输入存在标签拼写错误(emplyeeNumber、emploeeName),上述代码已修正为正确拼写,若需匹配原错误标签,可自行替换对应名称
InputVar2.xml
<Departs> <List> <employeeNumber>123</employeeNumber> <departName>fin</departName> <departId>10</departId> </List> <List> <employeeNumber>919</employeeNumber> <departName>adm</departName> <departId>20</departId> </List> <List> <employeeNumber>453</employeeNumber> <departName>hr</departName> <departId>30</departId> </List> </Departs>
期望输出
<WriteFile> <LinesRecordSet> <LinesRecord> <employeeNumber>123</employeeNumber> <departName>fin</departName> <departId>10</departId> <employeeName>abc</employeeName> </LinesRecord> <LinesRecord> <employeeNumber>453</employeeNumber> <departName>hr</departName> <departId>30</departId> <employeeName>cde</employeeName> </LinesRecord> <LinesRecord> <employeeNumber>678</employeeNumber> <departName></departName> <departId></departId> <employeeName>efg</employeeName> </LinesRecord> </LinesRecordSet> </WriteFile>
XSLT 2.0 解决方案
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义键,以员工编号为索引关联部门信息 --> <xsl:key name="dept-by-empnum" match="Departs/List" use="employeeNumber"/> <!-- 处理InputVar1的根节点 --> <xsl:template match="/Employees"> <WriteFile> <LinesRecordSet> <!-- 应用模板处理所有员工节点,替代for-each循环 --> <xsl:apply-templates select="List"/> </LinesRecordSet> </WriteFile> </xsl:template> <!-- 处理单个员工节点 --> <xsl:template match="List"> <LinesRecord> <!-- 复制员工编号 --> <xsl:copy-of select="employeeNumber"/> <!-- 获取部门名称,无匹配则为空 --> <departName> <xsl:value-of select="key('dept-by-empnum', employeeNumber)/departName"/> </departName> <!-- 获取部门ID,无匹配则为空 --> <departId> <xsl:value-of select="key('dept-by-empnum', employeeNumber)/departId"/> </departId> <!-- 复制员工姓名 --> <xsl:copy-of select="employeeName"/> </LinesRecord> </xsl:template> <!-- 忽略无关文本节点 --> <xsl:template match="text()"/> </xsl:stylesheet>
核心说明
- 键索引优化:通过
<xsl:key>建立员工编号与部门信息的映射,避免遍历整个部门列表,提升匹配效率。 - 模板驱动替代循环:使用
<xsl:apply-templates>触发模板匹配,自动处理每个员工节点,完全规避for-each的使用。 - 空值兼容:当员工无对应部门记录时,
value-of返回空字符串,自动生成空的部门元素,符合输出要求。
内容的提问来源于stack exchange,提问作者sum
相关产品推荐
相关产品推荐

