XSLT 2.0技术需求:移除含REMOVE操作的Position节点,保留其他内容
问题:移除含REMOVE操作的Position节点而非整个员工记录
需求说明
在XSLT 2.0中实现:当Position节点下的Operation子节点值为REMOVE时,移除该Position节点及其所有子节点,同时保留员工记录的其他所有内容。但当前编写的XSLT会删除整个员工记录,而非仅目标Position节点。
XML示例
<pi:Payroll_Extract_Employees xmlns:pi="urn:com.workday/picof"> <pi:PayGroup> <pi:Employee> <pi:Summary> <pi:Employee_ID>123456</pi:Employee_ID> <pi:Name>Ford Harrison</pi:Name> </pi:Summary> <pi:Status> <pi:Employee_Status>Active</pi:Employee_Status> <pi:Hire_Date>2024-05-07</pi:Hire_Date> </pi:Status> <pi:Position> <pi:Operation>ADD</pi:Operation> <pi:Position_ID pi:PriorValue=""> P38531 </pi:Position_ID> <pi:Business_Site pi:PriorValue=""> 3F_ABC </pi:Business_Site> </pi:Position> <pi:Position> <pi:Operation>REMOVE</pi:Operation> <pi:Position_ID>P3131236</pi:Position_ID> <pi:Business_Site>3F_EFG</pi:Business_Site> </pi:Position> </pi:Employee> </pi:PayGroup> </pi:Payroll_Extract_Employees>
期望输出
<EmployeeID>123456</EmployeeID> <EmployeeName>Ford Harrison</EmployeeName> <LocationName>3F ABC</LocationName>
当前错误的XSLT代码
OUTPUTS ALL ROWS EXCEPT EMPLOYEES WITH REMOVE OPERATION <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:pi="urn:com.workday/picof" exclude-result-prefixes="xs pi is" xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions" version="2.0"> <xsl:output method="xml" omit-xml-declaration="yes"/> <xsl:template match="/pi:Employee[not(/pi:Employee/pi:Position/pi:Operation = 'REMOVE')]"> <employee_record> <EmployeeID> <xsl:value-of select="/pi:Employee/pi:Summary/pi:Employee_ID"/> </EmployeeID> <EmployeeName> <xsl:value-of select="/pi:Employee/pi:Summary/pi:Name"/> </EmployeeName> <LocationName> <xsl:value-of select="replace(/pi:Employee/pi:Position/pi:Business_Site,'_',' ')"/> </LocationName> </employee_record> </xsl:template> </xsl:stylesheet>
解决方案
问题分析
- 模板匹配路径错误:原模板尝试匹配
/pi:Employee,但实际XML结构中Employee节点位于/pi:Payroll_Extract_Employees/pi:PayGroup下,路径不匹配导致模板无法正确触发。 - 条件逻辑错误:
not(/pi:Employee/pi:Position/pi:Operation = 'REMOVE')是检查整个文档中是否存在带REMOVE操作的员工,而非当前员工下的Position节点。这会直接排除所有包含REMOVE Position的员工,而非仅移除该Position。 - 绝对路径误用:所有节点选择都用了绝对路径
/pi:Employee,应该使用相对路径.引用当前匹配的员工节点,避免匹配错误的节点。 - 未处理多Position场景:原代码直接取所有Position的Business_Site,未过滤REMOVE的节点,会导致错误的Location值。
修正后的XSLT代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pi="urn:com.workday/picof" exclude-result-prefixes="pi" version="2.0"> <xsl:output method="xml" omit-xml-declaration="yes"/> <!-- 匹配根节点,遍历所有Employee节点 --> <xsl:template match="/"> <xsl:apply-templates select="pi:Payroll_Extract_Employees/pi:PayGroup/pi:Employee"/> </xsl:template> <!-- 处理每个Employee节点,生成期望的输出结构 --> <xsl:template match="pi:Employee"> <EmployeeID> <xsl:value-of select="normalize-space(pi:Summary/pi:Employee_ID)"/> </EmployeeID> <EmployeeName> <xsl:value-of select="normalize-space(pi:Summary/pi:Name)"/> </EmployeeName> <!-- 仅处理Operation为ADD的Position节点 --> <xsl:for-each select="pi:Position[pi:Operation = 'ADD']"> <LocationName> <xsl:value-of select="replace(normalize-space(pi:Business_Site), '_', ' ')"/> </LocationName> </xsl:for-each> </xsl:template> <!-- 身份模板,默认复制节点(本场景中主要确保其他未匹配节点不干扰) --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键说明
- 路径修正:通过
pi:Payroll_Extract_Employees/pi:PayGroup/pi:Employee正确定位员工节点。 - 过滤逻辑:使用
pi:Position[pi:Operation = 'ADD']仅选择需要保留的Position节点,自动排除REMOVE的节点。 - 文本处理:用
normalize-space()清理Business_Site中的多余空格,再用replace()替换下划线为空格,生成符合要求的LocationName。 - 结构生成:直接生成期望的扁平化输出节点,无需保留原XML结构。
内容的提问来源于stack exchange,提问作者mecc
相关产品推荐
相关产品推荐

