Search code examples
accumulatorxslt-3.0workday-api

XSLT error when adding accumulator logic to Web-service Request


I am creating an integration to load supplier invoices with multiple lines to workday after getting the details from an input file. Everything seems to be working as expected till i add accumulator logic in web service request in XSLT to first check if the cost center exists in workday. If it does then i populate that else i need to populate a default value. I have not built the default logic if cost center does not exist in the map yet.

I have created a custom report get all active cost center and i merge this list with my input file.

Sample data after i merge my custom report with input file -

<?xml version="1.0" encoding="utf-8"?>
<Header>
    <wd:Report_Data xmlns:wd="urn:com.workday.report/INT1007a_CR_PRC_FEDEX_Supplier_Invoices_Cost_Center">
        <wd:Report_Entry>
            <wd:CostCenter1>40720</wd:CostCenter1>
            <wd:CostCenter2>40720</wd:CostCenter2>
        </wd:Report_Entry>
    </wd:Report_Data>
    <root>
        <row>
            <col1>199779087</col1>
            <col2>652233142</col2>
            <col3>20190416</col3>
            <col4>O</col4>
            <col5>D</col5>
            <col6>000000000002256</col6>
            <col7>00002</col7>
            <col8>019153223</col8>
            <col9>US</col9>
            <col10>         </col10>
            <col11>        </col11>
            <col12>774894489995</col12>
            <col13>2</col13>
            <col14>20190406</col14>
            <col15>05</col15>
            <col16>06</col16>
            <col17>40720/PHL               </col17>
            <col18>1</col18>
            <col19>000000000001128</col19>
            <col20>USD</col20>
            <col21>050</col21>
            <col22>000000000002394</col22>
            <col23>+</col23>
            <col24>185</col24>
            <col25>000000000001345</col25>
            <col26>-</col26>
            <col27>010</col27>
            <col28>000000000000079</col28>
            <col29>+</col29>
            <col30>   </col30>
            <col31>000000000000000</col31>
            <col32> </col32>
            <col33>   </col33>
            <col34>000000000000000</col34>
            <col35> </col35>
            <col36>   </col36>
            <col37>000000000000000</col37>
            <col38> </col38>
            <col39>   </col39>
            <col40>000000000000000</col40>
            <col41> </col41>
            <col42>000000000</col42>
            <col43>200    </col43>
            <col44>00001</col44>
            <col45>0000000</col45>
            <col46>0000000</col46>
            <col47>L</col47>
            <col48>Test Test                 </col48>
            <col49>Test                         </col49>
            <col50>40720/PHL                </col50>
            <col51>Test            </col51>
            <col52>                              </col52>
            <col53>Test                  </col53>
            <col54>PA</col54>
            <col55>19103     </col55>
            <col56>US</col56>
            <col57>02</col57>
            <col58>Irshad Khan                   </col58>
            <col59>FINRA                         </col59>
            <col60>9513 Key West Avenue          </col60>
            <col61>                              </col61>
            <col62>ROCKVILLE                     </col62>
            <col63>MD</col63>
            <col64>20850     </col64>
            <col65>US</col65>
            <col66>20190408</col66>
            <col67>0836</col67>
            <col68>  </col68>
            <col69>00000000</col69>
            <col70>0000</col70>
            <col71>A.WANG                </col71>
            <col72>A1</col72>
            <col73>000000000000000</col73>
            <col74>USD</col74>
            <col75>   </col75>
            <col76>   </col76>
            <col77>   </col77>
            <col78>   </col78>
            <col79>                    </col79>
            <col80>          </col80>
            <col81>00000000</col81>
            <col82> </col82>
            <col83>                    </col83>
            <col84>000000001000000000</col84>
            <col85>USD</col85>
            <col86>40720/PHL                     </col86>
            <col87>                              </col87>
        </row>        
    </root>
</Header>

Below is my working XSLT i.e before adding accumulator logic -

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet             
            xmlns:wd="urn:com.workday/bsvc"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
            xmlns:map="http://www.w3.org/2005/xpath-functions/map"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:wd1="urn:com.workday.report/INT1007a_CR_PRC_FEDEX_Supplier_Invoices_Cost_Center"
            exclude-result-prefixes="wd xsl xsd"
            version="3.0">            
    <xsl:output method="xml"/>



    <xsl:param name="fpCompanyRefID"/>
    <xsl:param name="fpSupplierRefID"/>
    <xsl:param name="fpPaymentTermsRefID"/>
    <xsl:param name="fpSpendCategoryRefID"/>
    <xsl:param name="fpUOMRefID"/>
    <xsl:param name="fpWebServiceVersion"/>
    <xsl:param name="fpEventID"/>        

    <xsl:template match="/Header">
        <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <env:Body>
                <!--Group by Invoice Number to process all lines for an invoice-->
                <xsl:for-each-group select="root/row" group-by="col2">
                    <wd:Submit_Supplier_Invoice_Request xmlns:wd="urn:com.workday/bsvc" wd:Add_Only="true">
                        <xsl:attribute name="wd:version" select="$fpWebServiceVersion"/>
                        <wd:Business_Process_Parameters>
                            <!--When set to "true",all required approvals will be automatically marked as approved.-->
                            <!--<wd:Auto_Complete>true</wd:Auto_Complete> -->
                            <wd:Comment_Data>
                                <wd:Comment>
                                    <xsl:value-of select="concat('Integration Event WID : ',$fpEventID)"/>
                                </wd:Comment>
                            </wd:Comment_Data>
                        </wd:Business_Process_Parameters>
                        <wd:Supplier_Invoice_Data>
                            <!--Need to create Supplier Invoice in draft status. Therefore did not set this element.-->
                            <!--<wd:Submit>true</wd:Submit>-->
                            <wd:Company_Reference>
                                <wd:ID wd:type="Company_Reference_ID">
                                    <xsl:value-of select="$fpCompanyRefID"/>
                                </wd:ID>
                            </wd:Company_Reference>
                            <wd:Supplier_Reference>
                                <wd:ID wd:type="Supplier_ID">
                                    <xsl:value-of select="$fpSupplierRefID"/>
                                </wd:ID>
                            </wd:Supplier_Reference>
                            <wd:Invoice_Date><xsl:value-of select="format-date(col3,'[Y0001]-[M01]-[D01]')"/></wd:Invoice_Date>
                            <wd:Invoice_Date>
                                <xsl:value-of select="concat(substring(col3, 1, 4),'-',substring(col3,5, 2),'-',substring(col3, 7, 2))"/>
                            </wd:Invoice_Date>
                            <wd:Invoice_Received_Date>
                                <!-- <xsl:value-of select="format-date(current-date(),'[Y0001]-[M01]-[D01]')"/> -->
                            </wd:Invoice_Received_Date>
                            <wd:Control_Amount_Total>
                                <xsl:value-of select="col6 * 0.01"/>
                            </wd:Control_Amount_Total>
                            <!--<wd:Withholding_Tax_Amount><xsl:value-of select="col2"/></wd:Withholding_Tax_Amount>-->
                            <wd:Suppliers_Invoice_Number>
                                <xsl:value-of select="col2"/>
                            </wd:Suppliers_Invoice_Number>
                            <wd:Memo><xsl:value-of select="col8"/></wd:Memo>
                            <wd:Payment_Terms_Reference>
                                <wd:ID wd:type="Payment_Terms_ID">
                                    <xsl:value-of select="$fpPaymentTermsRefID"/>
                                </wd:ID>
                            </wd:Payment_Terms_Reference>
                            <wd:Gross_Invoice_Amount>
                                <xsl:value-of select="col6 * 0.01"/>
                            </wd:Gross_Invoice_Amount>
                            <!-- Process all the lines for the group. Grouping is done at the header level by Invoice Number-->
                            <xsl:for-each select="current-group()">
                                <wd:Invoice_Line_Replacement_Data>
                                    <wd:Item_Description>
                                        <xsl:value-of select="col12"/>
                                    </wd:Item_Description>
                                    <wd:Spend_Category_Reference>
                                        <wd:ID wd:type="Spend_Category_ID">
                                            <xsl:value-of select="$fpSpendCategoryRefID"/>
                                        </wd:ID>
                                    </wd:Spend_Category_Reference>
                                    <wd:Worktags_Reference>
                                        <wd:ID wd:type="Cost_Center_Reference_ID">
                                        55075                                                                                
                                        </wd:ID>
                                    </wd:Worktags_Reference>
                                    <wd:Worktags_Reference>
                                        <wd:ID wd:type="Project_ID">3333</wd:ID>
                                    </wd:Worktags_Reference>
                                    <wd:Worktags_Reference>
                                        <wd:ID wd:type="Location_ID">LOC_KWB</wd:ID>
                                    </wd:Worktags_Reference>
                                    <wd:Quantity>1</wd:Quantity>
                                    <wd:Unit_Cost>
                                        <xsl:value-of select="col19 * 0.01"/>
                                    </wd:Unit_Cost>
                                    <wd:Unit_of_Measure_Reference>
                                        <wd:ID wd:type="UN_CEFACT_Common_Code_ID">
                                            <xsl:value-of select="$fpUOMRefID"/>
                                        </wd:ID>
                                    </wd:Unit_of_Measure_Reference>
                                    <wd:Extended_Amount>
                                        <xsl:value-of select="col19 * 0.01"/>
                                    </wd:Extended_Amount>
                                    <wd:Memo><xsl:value-of select="concat('Sender Name: ',col48,' / Receiver Name: ', col58)"/></wd:Memo>
                                </wd:Invoice_Line_Replacement_Data>
                            </xsl:for-each>
                        </wd:Supplier_Invoice_Data>
                    </wd:Submit_Supplier_Invoice_Request>
                </xsl:for-each-group>
            </env:Body>
        </env:Envelope>
    </xsl:template>
</xsl:stylesheet>

But the moment I add below accumulator logic to above XSLT, Studio error out

  1. I am adding below code after -
    <xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="CostCenterLookup CurrentLookupValue"/>
    <xsl:output method="xml"/>

    <xsl:accumulator name="CurrentLookupValue" as="xs:string" initial-value="''" streamable="yes">
        <xsl:accumulator-rule match="wd:CostCenter1/text()" select="."/>
    </xsl:accumulator>

    <xsl:accumulator name="CostCenterLookup" as="map(xs:string,xs:string)" initial-value="map{}" streamable="yes">
        <xsl:accumulator-rule match="wd:CostCenter2/text()" select="map:put($value, accumulator-before('CurrentLookupValue'), string(.))"/>
    </xsl:accumulator>

  1. I am adding below code for getting value for Cost_Center_Reference_ID -
<xsl:value-of select="accumulator-before('CostCenterLookup')( normalize-space( substring(col17,1,5) ) )"/>

Error that I am getting is not very helpful to debug the exact issue -

Submit Supplier Invoice Request Failed for null. Error during invocation: null

Would really appreciate some help on this.


Solution

  • I would guess the error is simply caused by trying to use streaming (as you declare that on the xsl:mode) and xsl:for-each-group select="root/row" group-by="col2". With streaming you can't access child elements of the population elements (i.e. the row elements) in the group-by expression as that would require processing (consuming) the contents of each row. So you would need to use xsl:for-each-group select="root/row!copy-of()" group-by="col2". Otherwise the processor will reject the stylesheet code as not being streamable. You might want to try to use Saxon EE from the command line to verify, it for sure will give better diagnostics.