XSL multiple conditions greater than 0 - xslt-1.0

I have an XSL if that used work. TThe field in the table was defaulted to NULL. Some how they changed it on me and now it is defaulted to 0.0 Now my XSL is not working and I have been trying for days to figure out why. Sometimes choiceA or choiceB can be 0.whatevernumber
<xsl:if test="not(#choiceA = '0') or not(#choiceB = '0')">
<h2 class="course-heading">Big list of choiceA and choiceB</h2>
<span class="choice list-sq">
<ul>
<xsl:if test="not(#choiceA = '0')">
<li><xsl:value-of select="#choiceA"/> choiceAs</li>
</xsl:if>
</ul>
</span>
</xsl:if>

Related

CONVERT DATE INTO SQL format USING XSLT function

Input Date format : 2019-07-09-10.56.24.147431
Desired Date Format: 09-JUL-19
I need to do the above in XSLT (version 1.0)
I tried the below :
<xsl:value-of select="concat (substring (xp20:format-dateTime(substring(/ns0:outbound/ns0:cancel_wrk/ns0:hdr_data/ns0:ts_ext, 1,10),'[DD]-[MNn,3-3]-[YYYY]'), 1,6 ), substring (year-from-date (date(substring(/ns0:outbound/ns0:cancel_wrk/ns0:hdr_data/ns0:ts_ext, 1,10))), 3 ) )"/>
<tns:xtrnlSysDttm>
<xsl:value-of select="concat (substring (xp20:format-dateTime(substring(/ns0:outbound/ns0:cancel_wrk/ns0:hdr_data/ns0:ts_ext, 1,10),'[DD]-[MNn,3-3]-[YYYY]'), 1,6 ), substring (year-from-date (date(substring(/ns0:outbound/ns0:cancel_wrk/ns0:hdr_data/ns0:ts_ext, 1,10))), 3 ) )"/>
</tns:xtrnlSysDttm>
Error message while inserting into SQL database with the result of the above XSLT:
BINDING.JCA-12563
Exception occurred when binding was invoked.
Exception occurred during invocation of JCA binding: "JCA Binding execute of Reference operation 'insert' failed due to: DBWriteInteractionSpec Execute Failed Exception.
insert failed. Descriptor name: [GBE_INT_CSS_PQ_PQFFEFO.PqffefoProxy].
Caused by Exception [EclipseLink-3001] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [25-Aug-19], of class [class java.lang.String], could not be converted to [class java.sql.Timestamp].
Internal Exception: BINDING.JCA-11635
Could Not Convert Date Exception.
Unable to convert a string value in the xml to a java.sql.Date.
Even though databases accept strings representing dates in a variety of formats, the adapter only accepts strings representing dates in xml ISO date format.
The input value must be in the iso 8601 date format YYYY-MM-DD.
I assume Input Data
<root>
<input_date>2019-07-09-10.56.24.147431</input_date>
</root>
for XSL:-
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="1.0">
<xsl:template match="/">
<xsl:call-template name="MMM-DD-YYY">
<xsl:with-param name="date" select="'input_date'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="MMM-DD-YYY">
<xsl:param name="date"/>
<xsl:variable name="year" select="substring(substring-before(root/input_date, '-'), 3,2)"/>
<xsl:variable name="day" select="substring-before(substring-after(substring-after(root/input_date, '-'), '-'), '-')"/>
<xsl:variable name="month">
<xsl:call-template name="month-abbr">
<xsl:with-param name="month" select="substring-before(substring-after(root/input_date, '-'), '-')"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat($day,'-',$month,'-',$year)"/>
</xsl:template>
<xsl:template name="month-abbr">
<xsl:param name="month"/>
<xsl:choose>
<xsl:when test="$month = '01'">JAN</xsl:when>
<xsl:when test="$month = '02'">FEB</xsl:when>
<xsl:when test="$month = '03'">MAR</xsl:when>
<xsl:when test="$month = '04'">APR</xsl:when>
<xsl:when test="$month = '05'">MAY</xsl:when>
<xsl:when test="$month = '06'">JUN</xsl:when>
<xsl:when test="$month = '07'">JUL</xsl:when>
<xsl:when test="$month = '08'">AUG</xsl:when>
<xsl:when test="$month = '09'">SEP</xsl:when>
<xsl:when test="$month = '10'">OCT</xsl:when>
<xsl:when test="$month = '11'">NOV</xsl:when>
<xsl:when test="$month = '12'">DEC</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Get Output
09-JUL-19

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
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>
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.
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.

XSLT Increment reset upon change in element

XML:
<?xml version="1.0" encoding="utf-8"?>
<Projects>
<Project GUID="K9">
<Name>Range</Name>
<WBSs>
<WBS GUID="2">
<Name>Site</Name>
<ParentWBS/>
<ProjectGUID>K9</ProjectGUID>
<ObjectId>99040</ObjectId>
<Activities/>
<WBSs>
<WBS GUID="1">
<Name>West</Name>
<ParentWBS>2</ParentWBS>
<ProjectGUID>K9</ProjectGUID>
<ObjectId>99046</ObjectId>
<Activities>
<Activity GUID="A100">
<Name>Task</Name>
<ProjectGUID>K17</ProjectGUID>
<WBSCode>1</WBSCode>
</Activity>
</Activities>
</WBS>
<WBS GUID="2">
<Name>South</Name>
<ParentWBS>2</ParentWBS>
<ProjectGUID>K9</ProjectGUID>
<ObjectId>99047</ObjectId>
<Activities>
<Activity GUID="A200">
<Name>Task 2</Name>
</Activity>
</Activities>
</WBS>
<WBS GUID="3">
<Name>North</Name>
<ParentWBS>2</ParentWBS>
<ProjectGUID>K9</ProjectGUID>
<ObjectId>99048</ObjectId>
<Activities/>
</WBS>
</WBSs>
</WBS>
</WBSs>
<Activities/>
</Project>
</Projects>
This is my current output:
<OBJECTID>99046</OBJECTID >
<ACTIVITY>0010</ACTIVITY>
<OBJECTID>99047</OBJECTID >
<ACTIVITY>0020</ACTIVITY>
Desired output:
<OBJECTID>99046</OBJECTID >
<ACTIVITY>0010</ACTIVITY>
<OBJECTID>99047</OBJECTID >
<ACTIVITY>0010</ACTIVITY>
When I have existing Activity and existing OBJECTID, the first 2 WHEN clauses work fine. The problem arises when there is no existing
ObjectID or ObjectID changes in the 3rd WHEN. What I need is to start at ‘0010’ and increment by 10 until $ObjectID changes, then start at ‘0010’ again and so on. My background is procedural programming so still getting used to functional way of doing things and the restriction of not changing variables.
Thanks in advance.
Here's the relevant XSLT code:
<ACTIVITY>
<!-- count($ExistingActivity) = 1 -> ObjectId & Activity Id exist, increment $LastObjectIdActivity/ACTIVITY
count($ExistingObjectId) = 1 -> ObjectId exists, increment $LastObjectId/ACTIVITY
count($ExistingObjectId) = 0 -> $ObjectId start at 0010 and keep incrementing until ObjectId change.
-->
<xsl:variable name="incr" select="10"/>
<xsl:choose>
<xsl:when test="count($ExistingActivity) = 1"> <!-- Exact match of ObjectId & Activity -->
<!-- Get last existing ObjectId activity -->
<xsl:variable name="temp" select="$LastObjectIdActivity/ACTIVITY"/>
<xsl:variable name="Oper" select="format-number($temp, '0000')"/>
<xsl:value-of select="$Oper"/>
</xsl:when>
<xsl:when test="count($ExistingObjectId) = 1"> <!-- Activity not found, But ObjectId exists-->
<!-- Get last existing ObjectId activity -->
<xsl:variable name="temp" select="$LastObjectId/ACTIVITY + $incr"/>
<xsl:variable name="Oper" select="format-number($temp, '0000')"/>
<xsl:value-of select="$Oper"/>
</xsl:when>
<xsl:when test="count($ExistingObjectId) = 0"> <!-- No Existing ObjectId -->
<xsl:variable name="pos" select="(position() * 10)"/>
<xsl:variable name="NextOper" select="format-number($pos, '0000')"/> <!-- Start Activity at 0010 reset on new ObjectId-->
<xsl:value-of select="$NextOper"/>
<!-- $NextOper should be incremented by 10 -->
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</ACTIVITY>
I think what you want is to assign a value to each of the activities, so that's what you want to match
<xsl:template match="//Activity">
<OBJECTID>
<xsl:value-of select="../../ObjectId" />
</OBJECTID>
<ACTIVITY>
<xsl:value-of select="format-number(10 * (count(preceding-sibling::*) +1), '0000') "/>
</ACTIVITY>
</xsl:template>
That would give you the OBJECTID/ACTIVITY pair for every activity in the input. The count expression evaluates the number of preceding sibling activities, ie the 1-based index.

XSLT 1.0 to concatenate elements

I have a XML which has complex element called ExternalRequestIDs,
My requirement is to concatenate the ExternalRequestID values coming at run time.
If the input has 5 ExternalRequestID values then the 5 values needs to be concatenated.
The XSL i have created perform only static translation, am trying to accomplish this logic in xslt 1.0, i am new to xslt Please help
Source XML -
<?xml version="1.0" encoding="UTF-8" ?>
<RetrieveMIProcessRequest xmlns="http://xmlns.mycompany.com/RetrieveMI">
<ExternalRequestIDs>
<ExternalRequestID>ID1</ExternalRequestID>
</ExternalRequestIDs>
<ExternalRequestIDs>
<ExternalRequestID>ID2</ExternalRequestID>
</ExternalRequestIDs>
<ExternalRequestIDs>
<ExternalRequestID>ID3</ExternalRequestID>
</ExternalRequestIDs>
<SourceSystem>SourceSystemName</SourceSystem>
</RetrieveMIProcessRequest>
Transformation Created to Concatenate ExternalRequestID values -
<xsl:template match="/">
<ns0:RetrieveMIProcessRequest>
<xsl:for-each select="/ns0:RetrieveMIProcessRequest/ns0:ExternalRequestIDs">
<xsl:variable name="ExtId"
select="concat("'",/ns0:RetrieveMIProcessRequest/ns0:ExternalRequestIDs[1]/ns0:ExternalRequestID,"','",/ns0:RetrieveMIProcessRequest/ns0:ExternalRequestIDs[2]/ns0:ExternalRequestID"'")"/>
<ns0:ExternalRequestIDs>
<ns0:ExternalRequestID>
<xsl:value-of select="$ExtId"/>
</ns0:ExternalRequestID>
</ns0:ExternalRequestIDs>
</xsl:for-each>
<ns0:SourceSystem>
<xsl:value-of select="/ns0:RetrieveMIProcessRequest/ns0:SourceSystem"/>
</ns0:SourceSystem>
</ns0:RetrieveMIProcessRequest>
</xsl:template>
Output after transformation -
<?xml version = '1.0' encoding = 'UTF-8'?>
<ns0:RetrieveMIProcessRequest xmlns:ns0="http://xmlns.mycompany.com/RetrieveMI">
<ns0:ExternalRequestIDs>
<ns0:ExternalRequestID>'ID1','ID2'</ns0:ExternalRequestID>
</ns0:ExternalRequestIDs>
<ns0:ExternalRequestIDs>
<ns0:ExternalRequestID>'ID1','ID2'</ns0:ExternalRequestID>
</ns0:ExternalRequestIDs>
<ns0:ExternalRequestIDs>
<ns0:ExternalRequestID>'ID1','ID2'</ns0:ExternalRequestID>
</ns0:ExternalRequestIDs>
<ns0:SourceSystem>SourceSystemName</ns0:SourceSystem>
</ns0:RetrieveMIProcessRequest>
Expected Output -
<?xml version = '1.0' encoding = 'UTF-8'?>
<ns0:RetrieveMIProcessRequest xmlns:ns0="http://xmlns.mycompany.com/RetrieveMI">
<ns0:ExternalRequestIDs>
<ns0:ExternalRequestID>'ID1','ID2','ID3'</ns0:ExternalRequestID>
</ns0:ExternalRequestIDs>
<ns0:SourceSystem>SourceSystemName</ns0:SourceSystem>
</ns0:RetrieveMIProcessRequest>
This needs to be achieved at run based on the ExternalRequestID values coming in the input request.
If the input has 5 ExternalRequestID values then the values needs to be concatenated
OK, this template should fit your needs :
<xsl:template match="/">
<ns0:RetrieveMIProcessRequest>
<ns0:ExternalRequestIDs>
<ns0:ExternalRequestID>
<!-- Loop on all ExternalRequestID and concatenate the textual values -->
<xsl:for-each select="/ns0:RetrieveMIProcessRequest/ns0:ExternalRequestIDs/ns0:ExternalRequestID">
<xsl:text>'</xsl:text>
<xsl:value-of select="."/>
<xsl:text>'</xsl:text>
<xsl:if test="following::ns0:ExternalRequestID">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</ns0:ExternalRequestID>
</ns0:ExternalRequestIDs>
<ns0:SourceSystem>
<xsl:value-of select="/ns0:RetrieveMIProcessRequest/ns0:SourceSystem"/>
</ns0:SourceSystem>
</ns0:RetrieveMIProcessRequest>
</xsl:template>
The output I get is:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:RetrieveMIProcessRequest xmlns:ns0="http://xmlns.mycompany.com/RetrieveMI">
<ns0:ExternalRequestIDs>
<ns0:ExternalRequestID>'ID1','ID2','ID3'</ns0:ExternalRequestID>
</ns0:ExternalRequestIDs>
<ns0:SourceSystem>SourceSystemName</ns0:SourceSystem>
</ns0:RetrieveMIProcessRequest>

Conditional variable select in XSLT

I want a variable to have the value of an element if the value is numeric, but if it's not then I want the variable to have the value 0.
In other words, is there a simple equivalent of the following in XSLT?
var foobar = is_numeric(element value) ? element value : 0
Or how would you write this?
<xsl:variable name="foobar" select=" ? " />
XPath 1.0:
<xsl:variable name="foobar">
<xsl:choose>
<xsl:when test="number($value) = number($value)">
<xsl:value-of select="$value"/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Reference for this clever number($value) = number($value) numeric test: Dimitre Novatchev's answer to "Xpath test if is number" question.
In XPath 2.0 yes, you can use "castable as"
<xsl:variable name="foobar" as="xs:double"
select="if (x castable as xs:double) then x else 0" />
You could use:
<xsl:variable name="x"
select="(ELEMENT[. castable as xs:double], 0)[1]"/>
or
<xsl:variable name="x"
select="sum(ELEMENT[. castable as xs:double])"/>