【问题标题】:Key Match using accumulators in XSLT3在 XSLT3 中使用累加器进行键匹配
【发布时间】:2021-05-31 03:35:04
【问题描述】:

我希望在下面的 xslt3 中使用累加器,只处理不匹配的键并忽略其他键。

我想遍历每个 All_Time_Offs/Time_Off 并且如果 Time_Off_Key 存在于 Payroll_Input/Input_Key -> 然后不处理。否则处理记录

<?xml version="1.0" encoding="UTF-8"?>
<Aggregated_TimeOffs>
    <All_Payroll_Inputs>
        <Payroll_Input>
            <RefID>PAYROLL_INPUT-6-122898</RefID>
            <Emp_ID>101058</Emp_ID>
            <Earning>101D</Earning>
            <Start_Date/>
            <Adjustment>0</Adjustment>
            <Hours>4</Hours>
            <Input_Key>PAYROLL_INPUT-6-122898101D4</Input_Key>
        </Payroll_Input>
        <Payroll_Input>
            <RefID>PAYROLL_INPUT-6-122898</RefID>
            <Emp_ID>101058</Emp_ID>
            <Earning>101D</Earning>
            <Start_Date/>
            <Adjustment>0</Adjustment>
            <Hours>4</Hours>
            <Input_Key>PAYROLL_INPUT-6-122898101D9</Input_Key>
        </Payroll_Input>
    </All_Payroll_Inputs>
    <All_Time_Offs>
        <Time_Off>
            <RefID/>
            <Emp_ID>29519</Emp_ID>
            <Earning/>
            <Date>2020-09-10</Date>
            <Adjustment/>
            <Hours>7</Hours>
            <Cost_Center/>
            <Week>Week_2</Week>
            <Time_Off_Key>PAYROLL_INPUT-6-122898101D4</Time_Off_Key>
        </Time_Off>
        <Time_Off>
            <RefID/>
            <Emp_ID>68413</Emp_ID>
            <Earning/>
            <Date>2020-09-09</Date>
            <Adjustment/>
            <Hours>8</Hours>
            <Cost_Center/>
            <Week>Week_2</Week>
            <Time_Off_Key>INT024_PAYROLL_INPUT_2020-09-098</Time_Off_Key>
        </Time_Off>
    </All_Time_Offs>    
</Aggregated_TimeOffs> 

以下是我正在尝试但无法正常工作的 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:err="http://www.w3.org/2005/xqt-errors"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ext="urn:SomeExternalSource"
    xmlns:xtt="urn:com.workday/xtt"
    xmlns:wd="urn:com.workday/bsvc"
    xmlns:this="urn:com.workday/this"
    exclude-result-prefixes="xs ext map wd xtt this"
    version="3.0">
    
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"></xsl:output>
    
    <xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="Time_Off_Key Payroll_Input_lookup emp.id"/>
    
    <xsl:accumulator name="Payroll_Input_lookup" as="xs:string" initial-value="''" streamable="yes">
        <xsl:accumulator-rule match="Input_Key/text()" select="."/>
    </xsl:accumulator>
    
    <xsl:accumulator name="Time_Off_Key" as="map(xs:string,xs:string)" initial-value="map{}" streamable="yes">
        <xsl:accumulator-rule match="Time_Off_Key/text()" select="map:put($value, string(.), accumulator-before('Payroll_Input_lookup'))"/>
    </xsl:accumulator>
    
    <xsl:accumulator name="emp.id" streamable="yes" as="xs:string" initial-value="''">
        <xsl:accumulator-rule match="Emp_ID/text()" select="."/>
    </xsl:accumulator>
    
    <xsl:template match="Aggregated_TimeOffs">
        
        <xsl:for-each select="All_Time_Offs/Time_Off/copy-of()">
            
            <xsl:variable name="input_exists">
                <xsl:value-of select="accumulator-before('Time_Off_Key')(normalize-space(Time_Off_Key))"/>
            </xsl:variable>
            
            <xsl:if test="string-length($input_exists) &lt; 0">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 不清楚您想要/需要比较哪些值,我假设至少 Time_Off/Time_Off_KeyPayroll_Input/Input_Key,但您的代码似乎试图选择/存储 Emp_ID(来自哪个元素?),因此要修复代码,我们首先需要了解需求,无论您是想仅基于现有的Input_Key 删除Time_Off,还是还需要检查Emp_Id

标签: xslt-3.0


【解决方案1】:

如果您只想比较在“早期”解析 Payroll_Input/Input_Key 值期间出现的单个值 Time_Off_Key,那么单个 xs:string*,即基于字符串序列的累加器就足够了:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    
    <xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="Payroll_Input_Input_Keys"/>
    
    <xsl:accumulator name="Payroll_Input_Input_Keys" as="xs:string*" initial-value="()" streamable="yes">
        <xsl:accumulator-rule match="Payroll_Input/Input_Key/text()" select="., $value"/>
    </xsl:accumulator>
    
    <xsl:template match="Time_Off[copy-of()[not(Time_Off_Key = accumulator-before('Payroll_Input_Input_Keys'))]]">
      <xsl:copy-of select="."/>
    </xsl:template>
    
</xsl:stylesheet>

然而,它可能不是可流式的,因为在模式的谓词中使用 copy-of() 打破了可流式模式的无运动要求:所以我们需要编写

<xsl:template match="Time_Off">
    <xsl:copy-of select="copy-of()[not(Time_Off_Key = accumulator-before('Payroll_Input_Input_Keys'))]"/>
</xsl:template>

而不是让该代码与流媒体一起使用。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 2016-02-28
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    • 2016-12-29
    • 2011-04-13
    相关资源
    最近更新 更多