XSLT3.0中使用累加器执行Lookup无法返回值的问题
XSLT 3.0流处理Lookup返回空值的问题解决建议
问题说明
有一份来自两个数据源的聚合XML输入,使用包含三个累加器的XSLT 3.0代码进行Lookup操作,但Lookup返回空值,无法得到预期结果。
聚合输入XML
<?xml version="1.0" encoding="utf-8"?> <aggregate-data> <weci:Workers_Effective_Stack xmlns:weci="urn:com.workday/weci"> <weci:Worker> <weci:Worker_Summary> <weci:Employee_ID>11829</weci:Employee_ID> </weci:Worker_Summary> <weci:Effective_Change weci:Sequence="0"> <weci:Derived_Event_Code>TER</weci:Derived_Event_Code> </weci:Effective_Change> </weci:Worker> </weci:Workers_Effective_Stack> <persons xmlns:ext="urn:calabriopersons"> <person> <personid>00404e33-0c24-4846-b7db-b074006f4f25</personid> <wiserid>11829</wiserid> </person> <person> <personid>0043eeb1-1456-4ddf-b97c-b100009a79e9</personid> <wiserid>14119</wiserid> </person> </persons> </aggregate-data>
现有XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wtdf="urn:com.workday/weci/tdf" xmlns:weci="urn:com.workday/weci" xmlns:ext="urn:calabriopersons" exclude-result-prefixes="xs" version="3.0"> <xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="WorkerIDLookup CurrentLookupvalue"/> <xsl:output method="xml" indent="yes"/> <xsl:accumulator name="CurrentLookupvalue" as="xs:string" initial-value="''" streamable="yes"> <xsl:accumulator-rule match="ext:personid/text()" select="."/> </xsl:accumulator> <xsl:accumulator name="WorkerIDLookup" as="map(xs:string,xs:string)" initial-value="map{}" streamable="yes"> <xsl:accumulator-rule match="ext:wiserid/text()" select="map:put($value, string(.), accumulator-before('CurrentLookupvalue'))"/> </xsl:accumulator> <xsl:accumulator name="weciWorker" as="xs:string" initial-value="''" streamable="yes"> <xsl:accumulator-rule match="weci:Workers_Effective_Stack/weci:Worker/weci:Worker_Summary/weci:Employee_ID/text()" select="."/> </xsl:accumulator> <xsl:template match="weci:Workers_Effective_Stack"> <xsl:apply-templates select="copy-of(weci:Worker)[weci:Effective_Change/weci:Derived_Event_Code = 'HIR' or weci:Effective_Change/weci:Derived_Event_Code = 'TER']" mode="some-non-streamable-mode"/> </xsl:template> <xsl:template match="weci:Worker" mode="some-non-streamable-mode"> <xsl:for-each select="weci:Effective_Change[weci:Derived_Event_Code = 'TER']"> <Set-Leaving-Date> { "PersonId": "<xsl:value-of select="accumulator-before('WorkerIDLookup')( accumulator-before('weciWorker') )"/>" "Date": "2024-06-27" } </Set-Leaving-Date> </xsl:for-each> </xsl:template> </xsl:stylesheet>
预期输出
<?xml version="1.0" encoding="UTF-8"?> <Set-Leaving-Date xmlns:ext="urn:calabriopersons" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:weci="urn:com.workday/weci" xmlns:wtdf="urn:com.workday/weci/tdf"> { "PersonId": "00404e33-0c24-4846-b7db-b074006f4f25" "Date": "2024-06-27" } </Set-Leaving-Date>
实际输出
<?xml version="1.0" encoding="UTF-8"?> <Set-Leaving-Date xmlns:ext="urn:calabriopersons" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:weci="urn:com.workday/weci" xmlns:wtdf="urn:com.workday/weci/tdf"> { "PersonId": "" "Date": "2024-06-27" } </Set-Leaving-Date>
问题分析与修正方案
核心问题点
- 命名空间匹配错误:输入XML中的
personid和wiserid元素无命名空间(仅persons元素声明了ext前缀,但未设置默认命名空间),原代码中使用ext:personid和ext:wiserid无法匹配到目标节点,导致Lookup map未正确构建。 - 累加器未启用:
weciWorker累加器未添加到主模式的use-accumulators列表中,始终保持初始空值。 - 流处理顺序问题:输入中
weci:Workers_Effective_Stack节点在前,处理该节点时,后续的persons节点尚未被处理,WorkerIDLookup的map仍为空,无法查到对应值。 - 累加器调用时机错误:使用
accumulator-before获取Lookup map,此时map未完全构建完成,应使用accumulator-after确保所有数据已处理。
修正后的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wtdf="urn:com.workday/weci/tdf" xmlns:weci="urn:com.workday/weci" xmlns:ext="urn:calabriopersons" exclude-result-prefixes="xs" version="3.0"> <!-- 启用所有需要的累加器 --> <xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="WorkerIDLookup CurrentLookupvalue weciWorker"/> <xsl:output method="xml" indent="yes"/> <!-- 匹配无命名空间的personid --> <xsl:accumulator name="CurrentLookupvalue" as="xs:string" initial-value="''" streamable="yes"> <xsl:accumulator-rule match="personid/text()" select="."/> </xsl:accumulator> <!-- 匹配无命名空间的wiserid,构建Lookup映射 --> <xsl:accumulator name="WorkerIDLookup" as="map(xs:string,xs:string)" initial-value="map{}" streamable="yes"> <xsl:accumulator-rule match="wiserid/text()" select="map:put($value, string(.), accumulator-before('CurrentLookupvalue'))"/> </xsl:accumulator> <xsl:accumulator name="weciWorker" as="xs:string" initial-value="''" streamable="yes"> <xsl:accumulator-rule match="weci:Workers_Effective_Stack/weci:Worker/weci:Worker_Summary/weci:Employee_ID/text()" select="."/> </xsl:accumulator> <!-- 先处理persons节点构建Lookup映射,再处理Worker数据 --> <xsl:template match="aggregate-data"> <!-- 先遍历persons节点触发累加器构建映射 --> <xsl:apply-templates select="persons" mode="streamable"/> <!-- 再处理Worker数据 --> <xsl:apply-templates select="weci:Workers_Effective_Stack"/> </xsl:template> <xsl:template match="weci:Workers_Effective_Stack"> <xsl:apply-templates select="copy-of(weci:Worker)[weci:Effective_Change/weci:Derived_Event_Code = 'HIR' or weci:Effective_Change/weci:Derived_Event_Code = 'TER']" mode="some-non-streamable-mode"/> </xsl:template> <xsl:template match="weci:Worker" mode="some-non-streamable-mode"> <xsl:for-each select="weci:Effective_Change[weci:Derived_Event_Code = 'TER']"> <Set-Leaving-Date> { "PersonId": "<xsl:value-of select="accumulator-after('WorkerIDLookup')(weci:Worker_Summary/weci:Employee_ID)"/>" "Date": "2024-06-27" } </Set-Leaving-Date> </xsl:for-each> </xsl:template> </xsl:stylesheet>
修正说明
- 移除了
personid和wiserid匹配路径中的ext:前缀,确保匹配到无命名空间的目标节点。 - 将
weciWorker添加到主模式的use-accumulators列表,启用该累加器。 - 修改根节点模板,先处理
persons节点构建Lookup映射,再处理weci:Workers_Effective_Stack,确保Lookup map已完全构建。 - 在Lookup时直接从当前Worker节点获取
Employee_ID值,替代依赖累加器的方式,避免累加器值被后续Worker覆盖的问题;同时使用accumulator-after获取完整构建的Lookup map。
内容的提问来源于stack exchange,提问作者Arthi
相关产品推荐
相关产品推荐

