XSLT技术问询:如何按Person/UsrAddress/Code正确分组Reservation节点
XSLT按地址码分组Reservation节点解决方案
问题场景
现有如下XML导出文档:
<?xml version='1.0' encoding='UTF-8'?> <document> <header> <creation-date>2022-08-09T08:46:00</creation-date> <SequenceOfDocument>10</SequenceOfDocument> </header> <businessobjects> <Reservation> <BeginDateTime>2022-07-29T16:00:00</BeginDateTime> <OrderNumber>606.00</OrderNumber> <Person> <UsrAddress> <Code>0393</Code> </UsrAddress> </Person> <TotalActualCostExclVAT>30.00</TotalActualCostExclVAT> <ParentOrderRef/> </Reservation> <Reservation> <BeginDateTime>2022-07-29T16:00:00</BeginDateTime> <OrderNumber>606.01</OrderNumber> <RefBODefinitionUserDefined>UsrReservationEquipment</RefBODefinitionUserDefined> <Person> <UsrAddress> <Code>0393</Code> </UsrAddress> </Person> <TotalActualCostExclVAT>40.00</TotalActualCostExclVAT> <ParentOrderRef>606.00</ParentOrderRef> </Reservation> <Reservation> <BeginDateTime>2022-07-29T16:00:00</BeginDateTime> <OrderNumber>607.00</OrderNumber> <RefBODefinitionUserDefined>UsrReservationEquipment</RefBODefinitionUserDefined> <Person> <UsrAddress> <Code>0500</Code> </UsrAddress> </Person> <TotalActualCostExclVAT>50.00</TotalActualCostExclVAT> <ParentOrderRef></ParentOrderRef> </Reservation> </businessobjects> </document>
需要将所有Reservation节点按Person/UsrAddress/Code分组,生成如下结构的XML:
<SalesOrderHeader> <SalesOrderHeaderFields> <CustomerNumber>0393</CustomerNumber> </SalesOrderHeaderFields> <ItemFields> <_USERFIELD1>606.00</_USERFIELD1> </ItemFields> <ItemFields> <_USERFIELD1>606.01</_USERFIELD1> </ItemFields> </SalesOrderHeader> <SalesOrderHeader> <SalesOrderHeaderFields> <CustomerNumber>0500</CustomerNumber> </SalesOrderHeaderFields> <ItemFields> <_USERFIELD1>607.00</_USERFIELD1> </ItemFields> </SalesOrderHeader>
错误原因分析
原尝试的代码中,group-by="/Person/UsrAddress/Code"使用了绝对路径,会从XML根节点开始查找Person元素,而当前上下文是Reservation节点,正确的路径应该是相对路径Person/UsrAddress/Code。此外,需确保使用支持XSLT 2.0及以上版本的处理器(如Saxon),因为<xsl:for-each-group>是XSLT 2.0引入的特性。
完整XSLT解决方案
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 匹配根节点 --> <xsl:template match="/document"> <!-- 遍历businessobjects下的Reservation节点,按Person/UsrAddress/Code分组 --> <xsl:for-each-group select="businessobjects/Reservation" group-by="Person/UsrAddress/Code"> <!-- 生成每个分组的SalesOrderHeader --> <SalesOrderHeader> <SalesOrderHeaderFields> <!-- 使用分组键作为CustomerNumber --> <CustomerNumber><xsl:value-of select="current-grouping-key()"/></CustomerNumber> </SalesOrderHeaderFields> <!-- 遍历当前分组内的所有Reservation节点 --> <xsl:for-each select="current-group()"> <ItemFields> <_USERFIELD1><xsl:value-of select="OrderNumber"/></_USERFIELD1> </ItemFields> </xsl:for-each> </SalesOrderHeader> <!-- 添加换行分隔不同的SalesOrderHeader --> <xsl:text> </xsl:text> </xsl:for-each-group> </xsl:template> </xsl:stylesheet>
关键说明
group-by="Person/UsrAddress/Code":基于当前Reservation节点下的相对路径获取分组键,确保正确匹配每个Reservation对应的地址码。current-grouping-key():直接获取当前分组的键值(即地址码),用于填充CustomerNumber。current-group():返回当前分组内的所有Reservation节点,遍历生成对应的ItemFields。
内容的提问来源于stack exchange,提问作者Ma Kul
相关产品推荐
相关产品推荐

