I'm having an XML and likes to retrieve and concatenate values
Below is the Sample XML from which we need to retrieve the values:
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<docBody>
<employee>
<employeeNumber>595</employeeNumber>
</employee>
<employeeAddress>
<empAddress>1</empAddress>
<empAddress2>1</empAddress2>
</employeeAddress>
</docBody>
<Messages />
</Document>
Method1:
<xsl:template match="employee">
<xsl:variable name="empNbr">
<xsl:value-of select="employeeNumber"/>
</xsl:variable>
<xsl:variable name="empAddress">
<xsl:value-of select="../employeeDetails/employeeAddress"/>
</xsl:variable>
<xsl:variable name="empAddress2">
<xsl:value-of select="../employeeDetails/empAddress2"/>
</xsl:variable>
<xsl:value-of select="concat($empNbr,$empAddress,$empAddress2)"/>
</xsl:template>
Method2:
<xsl:template match="employee">
<xsl:value-of select="concat(<xsl:value-of select="employeeNumber"/>,
<xsl:value-of select="../employeeDetails/employeeAddress"/>,
<xsl:value-of select="../employeeDetails/empAddress2"/>)"/>
</xsl:template>
Thanks in advance.
It's usually better to write variable declarations like so
<xsl:variable name="empNbr" select="employeeNumber" />
This means empNbr now references the employeeNumber directly. By using xsl:value-of this effectively gets the text value of empNbr and assigns it to the variable.
Your second method is not valid XSLT. The expression you are looking for is this...
<xsl:value-of select="concat(employeeNumber, ../employeeDetails/employeeAddress, ../employeeDetails/empAddress2)" />
Or you could have three separate xsl:value-of statements.
<xsl:value-of select="employeeNumber"/>
<xsl:value-of select="../employeeDetails/employeeAddress"/>
<xsl:value-of select="../employeeDetails/empAddress2"/>
Related
I read lot of articles but did not find a conclusive help to my problem.
I have an XML document to which I apply an xslt to get a csv file as output.
I send a parameter to my xsl transformation to filter the target nodes to apply the templates.
The xml document looks like that (I removed some unuseful nodes for comprehension):
<GetMOTransactionsResponse xmlns="http://www.exane.com/pott" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exane.com/pott PoTTMOTransaction.xsd">
<MOTransaction>
<Transaction VersionNumber="2" TradeDate="2013-11-20">
<TransactionId Type="Risque">32164597</TransactionId>
<InternalTransaction Type="Switch">
<BookCounterparty>
<Id Type="Risque">94</Id>
</BookCounterparty>
</InternalTransaction>
<SalesPerson>
<Id Type="Risque">-1</Id>
</SalesPerson>
</Transaction>
<GrossPrice>58.92</GrossPrice>
<MOAccount Account="TO1E" />
<Entity>0021</Entity>
</MOTransaction>
<MOTransaction>
<Transaction VersionNumber="1" TradeDate="2013-11-20">
<TransactionId Type="Risque">32164598</TransactionId>
<SalesPerson>
<Id Type="Risque">-1</Id>
</SalesPerson>
</Transaction>
<GrossPrice>58.92</GrossPrice>
<MOAccount Account="TO3E" />
<Entity>0021</Entity>
</MOTransaction>
</GetMOTransactionsResponse>
My xslt is below (sorry it's quite long, and I write it more simple than it really is):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:pott="http://www.exane.com/pott">
<xsl:output method="text" omit-xml-declaration="no" indent="no" />
<xsl:param name="instrumentalSystem"></xsl:param>
<xsl:template name="abs">
<xsl:param name="n" />
<xsl:choose>
<xsl:when test="$n = 0">
<xsl:text>0</xsl:text>
</xsl:when>
<xsl:when test="$n > 0">
<xsl:value-of select="format-number($n, '#')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="format-number(0 - $n, '#')" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="outputFormat">
<!--Declaration of variables-->
<xsl:variable name="GrossPrice" select="pott:GrossPrice" />
<xsl:variable name="TransactionId" select="pott:Transaction/pott:TransactionId[#Type='Risque']" />
<xsl:variable name="VersionNumber" select="pott:Transaction/#VersionNumber" />
<!--Set tags values-->
<xsl:value-of select="$Entity" />
<xsl:text>;</xsl:text>
<xsl:value-of select="concat('0000000', pott:MOAccount/#Account) "/>
<xsl:text>;</xsl:text>
<xsl:text>;</xsl:text>
<xsl:value-of select="$TransactionId" />
<xsl:text>;</xsl:text>
<xsl:value-of select="$VersionNumber" />
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:choose>
<!-- BB -->
<xsl:when test="$instrumentalSystem = 'BB'">
<!--xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction/pott:Transaction[pott:InternalTransaction]"-->
<xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction/pott:Transaction[pott:InternalTransaction]">
<xsl:call-template name="outputFormat"></xsl:call-template>
</xsl:for-each>
</xsl:when>
<!-- CP -->
<xsl:when test="$instrumentalSystem = 'CP'">
<xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction/pott:Transaction[not(pott:InternalTransaction)]">
<xsl:call-template name="outputFormat"></xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
If parameter = BB, I want to select MOTransaction nodes that have a child Transaction that contains a InternalTransaction node.
If parameter = CP, I want to select MOTransaction nodes that don't have a child Transaction that contains a InternalTransaction node
When I write
pott:GetMOTransactionsResponse/pott:MOTransaction/pott:Transaction[pott:InternalTransaction], I get the Transaction nodes and not the MOTransaction nodes
I think I am not very far from the expected result, but despite all my attempts, I fail.
If anyone can help me.
I hope being clear, otherwise I can give more information.
Looking at one of xsl:for-each statements, you are doing this
<xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction/pott:Transaction[pott:InternalTransaction]">
You say you want to select MOTransaction elements, but it is actually selecting the child Transaction elements. To match the logic you require, it should be this
<xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction[pott:Transaction[pott:InternalTransaction]]">
In fact, this should also work
<xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction[pott:Transaction/pott:InternalTransaction]">
Similarly, for the second statement (in the case of the parameter being "CP"), it could look like this
<xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction[pott:Transaction[not(pott:InternalTransaction)]]">
Alternatively, it could look like this
<xsl:for-each select="pott:GetMOTransactionsResponse/pott:MOTransaction[not(pott:Transaction/pott:InternalTransaction)]">
They are not quite the same though, as the first will only include MOTransaction elements that have Transaction child elements, whereas the second will include MOTransaction that don't have any Transaction childs at all.
As a slight aside, you don't really need to use an xsl:for-each and xsl:call-template here. It might be better to use template matching.
Firstly, try changing the named template <xsl:template name="outputFormat"> to this
<xsl:template match="pott:MOTransaction">
Then, you can re-write you merge the xsl:for-each and xsl:call-template into a single xsl:apply-templates call.
<xsl:apply-template select="pott:GetMOTransactionsResponse/pott:MOTransaction[pott:Transaction/pott:InternalTransaction]" />
I have a specific problem. I have to transform an XML structure to other, where the base XSD is same, different only the namespace definition. The first part is simple, because here I have to use field-mapping. The second part is the simple copy. And here is the problem. The copied "main" node contains the original xmlns attribute. I need to remove this "attribute".
The base xml:
<?xml version="1.0" encoding="UTF-8"?>
<S2SCTIcf:SCTIcfBlkCredTrf xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf SCTIcfBlkCredTrf.xsd">
<S2SCTIcf:SndgInst>XXXXXXX0</S2SCTIcf:SndgInst>
<S2SCTIcf:RcvgInst>YYYYYYY0</S2SCTIcf:RcvgInst>
<S2SCTIcf:FileRef>2013111200800546</S2SCTIcf:FileRef>
<S2SCTIcf:SrvcId>SCT</S2SCTIcf:SrvcId>
<S2SCTIcf:TstCode>T</S2SCTIcf:TstCode>
<S2SCTIcf:FType>ICF</S2SCTIcf:FType>
<S2SCTIcf:FDtTm>2013-11-12T16:26:31</S2SCTIcf:FDtTm>
<S2SCTIcf:NumCTBlk>1</S2SCTIcf:NumCTBlk>
<S2SCTIcf:NumPCRBlk>0</S2SCTIcf:NumPCRBlk>
<S2SCTIcf:NumRFRBlk>0</S2SCTIcf:NumRFRBlk>
<S2SCTIcf:NumROIBlk>0</S2SCTIcf:NumROIBlk>
<S2SCTIcf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
<GrpHdr>
<MsgId>xxddccxxaaa</MsgId>
<CreDtTm>2013-11-12T16:26:31</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<TtlIntrBkSttlmAmt Ccy="EUR">469.12</TtlIntrBkSttlmAmt>
<IntrBkSttlmDt>2013-11-13</IntrBkSttlmDt>
<SttlmInf>
<SttlmMtd>CLRG</SttlmMtd>
<ClrSys>
<Prtry>ST2</Prtry>
</ClrSys>
</SttlmInf>
<InstgAgt>
<FinInstnId>
<BIC>XXXXXXX0</BIC>
</FinInstnId>
</InstgAgt>
</GrpHdr>
<CdtTrfTxInf>
<PmtId>
<EndToEndId>1114405599,1114382976</EndToEndId>
<TxId>F3232323232</TxId>
</PmtId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
<IntrBkSttlmAmt Ccy="EUR">469.12</IntrBkSttlmAmt>
<ChrgBr>SLEV</ChrgBr>
<Dbtr>
<Nm>ddffrrddsaasas</Nm>
<PstlAdr>
<Ctry>HU</Ctry>
<AdrLine>dssdsdsdsdsdaas</AdrLine>
</PstlAdr>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>HU26XXXXXXXXXXXXXX</IBAN>
</Id>
</DbtrAcct>
<DbtrAgt>
<FinInstnId>
<BIC>CCCCHUH0</BIC>
</FinInstnId>
</DbtrAgt>
<CdtrAgt>
<FinInstnId>
<BIC>CVCVCVCVCVC</BIC>
</FinInstnId>
</CdtrAgt>
<Cdtr>
<Nm>XXXXX</Nm>
<PstlAdr>
<Ctry>DE</Ctry>
</PstlAdr>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>DE12vvvvvvvhghhg</IBAN>
</Id>
</CdtrAcct>
<RmtInf>
<Ustrd>0000000000,0000000000 </Ustrd>
</RmtInf>
</CdtTrfTxInf>
</S2SCTIcf:FIToFICstmrCdtTrf>
</S2SCTIcf:SCTIcfBlkCredTrf>
The xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns0="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf"
xmlns:sw8="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02"
xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf" exclude-result-prefixes="xs ns0 ">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="var1_SCTIcfBlkCredTrf" select="ns0:SCTIcfBlkCredTrf"/>
<S2SCTScf:SCTScfBlkCredTrf
xsi:schemaLocation="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf SCTScfBlkCredTrf.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf">
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:SndgInst>
<xsl:value-of select="string(ns0:RcvgInst)"/>
</S2SCTScf:SndgInst>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:RcvgInst>
<xsl:value-of select="string(ns0:SndgInst)"/>
</S2SCTScf:RcvgInst>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:SrvcId>
<xsl:value-of select="string(ns0:SrvcId)"/>
</S2SCTScf:SrvcId>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:TstCode>
<xsl:value-of select="string(ns0:TstCode)"/>
</S2SCTScf:TstCode>
</xsl:for-each>
<S2SCTScf:FType>SCF</S2SCTScf:FType>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:FileRef>
<xsl:value-of select="string(ns0:FileRef)"/>
</S2SCTScf:FileRef>
</xsl:for-each>
<S2SCTScf:RoutingInd>DIR</S2SCTScf:RoutingInd>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:FileBusDt>
<xsl:value-of select="string(ns0:FDtTm)"/>
</S2SCTScf:FileBusDt>
</xsl:for-each>
<S2SCTScf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<GrpHdr>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<MsgId>
<xsl:value-of select="string(sw8:GrpHdr/sw8:MsgId)"/>
</MsgId>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<CreDtTm>
<xsl:value-of select="string(sw8:GrpHdr/sw8:CreDtTm)"/>
</CreDtTm>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<NbOfTxs>
<xsl:value-of select="string(sw8:GrpHdr/sw8:NbOfTxs)"/>
</NbOfTxs>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<xsl:variable name="var2_TtlIntrBkSttlmAmt"
select="sw8:GrpHdr/sw8:TtlIntrBkSttlmAmt"/>
<TtlIntrBkSttlmAmt>
<xsl:attribute name="Ccy" namespace="">
<xsl:value-of select="string($var2_TtlIntrBkSttlmAmt/#Ccy)"/>
</xsl:attribute>
<xsl:value-of
select="string(number(string($var2_TtlIntrBkSttlmAmt)))"/>
</TtlIntrBkSttlmAmt>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<IntrBkSttlmDt>
<xsl:value-of select="string(sw8:GrpHdr/sw8:IntrBkSttlmDt)"/>
</IntrBkSttlmDt>
</xsl:for-each>
<SttlmInf>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<SttlmMtd>
<xsl:value-of
select="string(sw8:GrpHdr/sw8:SttlmInf/sw8:SttlmMtd)"/>
</SttlmMtd>
</xsl:for-each>
<ClrSys>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<Prtry>
<xsl:value-of
select="string(sw8:GrpHdr/sw8:SttlmInf/sw8:ClrSys/sw8:Prtry)"
/>
</Prtry>
</xsl:for-each>
</ClrSys>
</SttlmInf>
<InstdAgt>
<FinInstnId>
<xsl:for-each
select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:GrpHdr/sw8:InstgAgt">
<BIC>
<xsl:value-of select="string(sw8:FinInstnId/sw8:BIC)"/>
</BIC>
</xsl:for-each>
</FinInstnId>
</InstdAgt>
</GrpHdr>
<xsl:copy-of select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />
</xsl:for-each>
</S2SCTScf:FIToFICstmrCdtTrf>
</S2SCTScf:SCTScfBlkCredTrf>
</xsl:template>
</xsl:stylesheet>
The wrong part of output:
...
</InstdAgt>
</GrpHdr>
<CdtTrfTxInf xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf">
<PmtId>
<EndToEndId>1114405599,1114382976</EndToEndId>
<TxId>F3232323232</TxId>
...
I don't want to get the xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf" attribute this line.
Have someone any idea?
Thank you!
Feri
Your issue is that
<xsl:copy-of select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />
copies the node from the original tree including its "namespace nodes", i.e. the namespace declarations that were in scope at that point in the original document. When this node is serialized any of these namespace nodes that are not already in force at this point in the output document will be declared by the serializer.
If you were able to use XSLT 2.0 then you could try setting copy-namespaces="no" on the copy-of but that isn't an option in XSLT 1.0. So instead of using copy-of you need to use templates to copy that node (and all its descendants recursively) without including the namespace nodes. The simplest way I can think of to do this is to declare two additional templates
<xsl:template match="*" mode="copy">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="#*|node()" mode="copy" />
</xsl:element>
</xsl:template>
<xsl:template match="#*|text()|comment()" mode="copy">
<xsl:copy/>
</xsl:template>
and then replace that copy-of with
<xsl:apply-templates mode="copy"
select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />
The trick here is that xsl:element is creating a new element node that happens to have the same name and namespace as the original one, rather than copying the original node, so it doesn't copy the namespace nodes.
You can use a variant of the answer here to get what you want.
Basically, you would create a template to rebuild that element without any namespaces. So you would add the following two templates to your current XSLT:
<xsl:template match="*" mode="copy-no-namespaces">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
</xsl:element>
</xsl:template>
<xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
<xsl:copy/>
</xsl:template>
And then update your copy-of to
<xsl:apply-templates select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" mode="copy-no-namespaces"/>
We have a requirement where we are getting an XML payload in form of String for one node and we need to expand this XML and pass the XML node values to destination XSD columns.
For example Input XSD :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Transaction xmlns="http://xmlns.oracle.com/2012/SCEM">
<TRXKEY>0x0000013</TRXKEY>
<EVENTNAME>SalesOrder</EVENTNAME>
<ACCEPTEDQUANTITY>0</ACCEPTEDQUANTITY>
<ORDEREDQUANTITY>0</ORDEREDQUANTITY>
<SOLORGID>0</SOLORGID>
<LHORDERHOLDIDRELEASED>0</LHORDERHOLDIDRELEASED>
<ORDEREDQUANTITYUOM>0</ORDEREDQUANTITYUOM>
<UNITSELLINGPRICE>0</UNITSELLINGPRICE>
<ORDERTYPE><Val lang='AR'>OrderTypeARARARAR</Val>
<Val lang='KO'>OrderTypeKOKOKOKO</Val>
<Val lang='US'>OrderTypeUSUSUUS</Val>
</ORDERTYPE>
</Transaction>
Output XML
<Transaction1 xmlns="http://xmlns.oracle.com/2012/SCEM">
<TRXKEY>0x0000013</TRXKEY>
<EVENTNAME>SalesOrder</EVENTNAME>
<ACCEPTEDQUANTITY>0</ACCEPTEDQUANTITY>
<ORDEREDQUANTITY>0</ORDEREDQUANTITY>
<SOLORGID>0</SOLORGID>
<LHORDERHOLDIDRELEASED>0</LHORDERHOLDIDRELEASED>
<ORDEREDQUANTITYUOM>0</ORDEREDQUANTITYUOM>
<UNITSELLINGPRICE>0</UNITSELLINGPRICE>
<ORDERTYPE_AR>OrderTypeARARARAR</ORDERTYPE_AR>
<ORDERTYPE_US>OrderTypeUSUSUUS</ORDERTYPE_US>
<ORDERTYPE_KO>OrderTypeKOKOKOKO</ORDERTYPE_KO>
</Transaction>
We need to loop through the ORDERTYPE node XML string. Depending on the 'Val lang=' value we need to pass this node value to output XSD ORDERTYPE_$lang value column.
How can I loop through this XML string for these 2 different values and pass it to the corresponding output XML column?
I was thinking of using split but it is not helping much.
Thanks Martin,
I have come up with below code which resolved my issue.
<xsl:stylesheet version="1.0"
xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
xmlns:mhdr="http://www.oracle.com/XSL/Transform/java/oracle.tip.mediator.service.common.functions.MediatorExtnFunction"
xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dvm="http://www.oracle.com/XSL/Transform/java/oracle.tip.dvm.LookupValue"
xmlns:hwf="http://xmlns.oracle.com/bpel/workflow/xpath"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:med="http://schemas.oracle.com/mediator/xpath"
xmlns:ids="http://xmlns.oracle.com/bpel/services/IdentityService/xpath"
xmlns:bpm="http://xmlns.oracle.com/bpmn20/extensions"
xmlns:client="http://xmlns.oracle.com/KeyStore/emsProjXslt/BPELProcess1"
xmlns:xdk="http://schemas.oracle.com/bpel/extension/xpath/function/xdk"
xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions"
xmlns:ns2="http://xmlns.oracle.com/2012/SCEM"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:ora="http://schemas.oracle.com/xpath/extension"
xmlns:socket="http://www.oracle.com/XSL/Transform/java/oracle.tip.adapter.socket.ProtocolTranslator"
xmlns:ldap="http://schemas.oracle.com/xpath/extension/ldap"
exclude-result-prefixes="xsi xsl client ns2 plnk xsd wsdl bpws xp20 mhdr bpel oraext dvm hwf med ids bpm xdk xref ora socket ldap">
<xsl:template match="/">
<ns2:Transaction>
<ns2:TRXKEY>
<xsl:value-of select="/ns2:Transaction/ns2:TRXKEY"/>
</ns2:TRXKEY>
<xsl:call-template name="for.loop.Parameters">
<xsl:with-param name="sourceNodes"
select='substring-after(/ns2:Transaction/ns2:ORDERTYPE,"Val lang=")'/>
</xsl:call-template>
</ns2:Transaction>
</xsl:template>
<xsl:template name="for.loop.Parameters">
<xsl:param name="sourceNodes"/>
<xsl:variable name="temp">
<xsl:choose>
<xsl:when test="string-length($sourceNodes) > '0'">
<xsl:value-of select="substring-before($sourceNodes,'</Val>')"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="Expression" select="substring-after($temp, '>')"/>
<xsl:variable name="Expression1" select="substring-before($temp, '>')"/>
<xsl:if test="contains($Expression1,'AR')">
<ns2:ORDERTYPE_AR>
<xsl:value-of select="$Expression"/>
</ns2:ORDERTYPE_AR>
</xsl:if>
<xsl:if test="contains($Expression,'US')">
<ns2:ORDERTYPE_US>
<xsl:value-of select="$Expression"/>
</ns2:ORDERTYPE_US>
</xsl:if>
<xsl:if test="contains($Expression,'KO')">
<ns2:ORDERTYPE_KO>
<xsl:value-of select="$Expression"/>
</ns2:ORDERTYPE_KO>
</xsl:if>
<xsl:variable name="test">
<xsl:value-of select="substring-after($sourceNodes,'/Val>')"/>
</xsl:variable>
<xsl:if test="string-length($test) > 1 ">
<xsl:call-template name="for.loop.Parameters">
<xsl:with-param name="sourceNodes">
<xsl:value-of select='substring-after($test,"Val lang=")'/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
This is in continuation of my question:
Merge functionality of two xsl files into a single file (not a xsl import or include issue)
I have to merge the solution (xsl) of above question to below xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<Declaration>
<Message>
<Meduim>
<xsl:value-of select="/Declaration/Message/Meduim"/>
</Meduim>
<MessageIdentifier>
<xsl:value-of select="/Declaration/Message/MessageIdentifier"/>
</MessageIdentifier>
<ControlingAgencyCode>
<xsl:value-of select="/Declaration/Message/ControlingAgencyCode"/>
</ControlingAgencyCode>
<AssociationAssignedCode>
<xsl:value-of select="/Declaration/Message/AssociationAssignedCode"/>
</AssociationAssignedCode>
<CommonAccessReference>
<xsl:value-of select="/Declaration/Message/CommonAccessReference"/>
</CommonAccessReference>
</Message>
<BeginingOfMessage>
<MessageCode>
<xsl:value-of select="/Declaration/BeginingOfMessage/MessageCode"/>
</MessageCode>
<DeclarationCurrency>
<xsl:value-of select="/Declaration/BeginingOfMessage/DeclarationCurrency"/>
</DeclarationCurrency>
<MessageFunction>
<xsl:value-of select="/Declaration/BeginingOfMessage/MessageFunction"/>
</MessageFunction>
</BeginingOfMessage>
<Header>
<ProcessingInformation>
<xsl:for-each select="/Declaration/Header/ProcessingInformation/ProcessingInstructions">
<ProcessingInstructions>
<xsl:value-of select="."/>
</ProcessingInstructions>
</xsl:for-each>
</ProcessingInformation>
<xsl:for-each select="/Declaration/Header/Seal">
<Seal>
<SealID>
<xsl:value-of select="SealID"/>
</SealID>
<SealLanguage>
<xsl:value-of select="SealLanguage"/>
</SealLanguage>
</Seal>
</xsl:for-each>
<xsl:choose>
<xsl:when test='/Declaration/Header/DeclarantsReference = ""'>
<DeclarantsReference>
<xsl:text disable-output-escaping="no">A</xsl:text>
</DeclarantsReference>
</xsl:when>
<xsl:otherwise>
<DeclarantsReference>
<xsl:value-of select="/Declaration/Header/DeclarantsReference"/>
</DeclarantsReference>
</xsl:otherwise>
</xsl:choose>
<xsl:for-each select="/Declaration/Header/Items">
<Items>
<CustomsStatusOfGoods>
<CPC>
<xsl:value-of select="CustomsStatusOfGoods/CPC"/>
</CPC>
<CommodityCode>
<xsl:value-of select="CustomsStatusOfGoods/CommodityCode"/>
</CommodityCode>
<ECSuplementaryMeasureCode1>
<xsl:value-of select="CustomsStatusOfGoods/ECSuplementaryMeasureCode1"/>
</ECSuplementaryMeasureCode1>
<ECSuplementaryMeasureCode2>
<xsl:value-of select="CustomsStatusOfGoods/ECSuplementaryMeasureCode2"/>
</ECSuplementaryMeasureCode2>
<PreferenceCode>
<xsl:value-of select="CustomsStatusOfGoods/PreferenceCode"/>
</PreferenceCode>
</CustomsStatusOfGoods>
<xsl:for-each select="ItemAI">
<ItemAI>
<AICode>
<xsl:value-of select="AICode"/>
</AICode>
<AIStatement>
<xsl:value-of select="AIStatement"/>
</AIStatement>
<AILanguage>
<xsl:value-of select="AILanguage"/>
</AILanguage>
</ItemAI>
</xsl:for-each>
<Locations>
<CountryOfOriginCode>
<xsl:value-of select="Locations/CountryOfOriginCode"/>
</CountryOfOriginCode>
<xsl:for-each select="Locations/ItemCountryonRouteCode">
<ItemCountryonRouteCode>
<xsl:value-of select="."/>
</ItemCountryonRouteCode>
</xsl:for-each>
<ItemDispatchCountry>
<xsl:value-of select="Locations/ItemDispatchCountry"/>
</ItemDispatchCountry>
<ItemDestinationCountry>
<xsl:value-of select="Locations/ItemDestinationCountry"/>
</ItemDestinationCountry>
</Locations>
<Measurements>
<GrossMass>
<xsl:value-of select="Measurements/GrossMass"/>
</GrossMass>
<NetMass>
<xsl:value-of select="Measurements/NetMass"/>
</NetMass>
<SupplementaryUnits>
<xsl:value-of select="Measurements/SupplementaryUnits"/>
</SupplementaryUnits>
<ThirdQuantity>
<xsl:value-of select="Measurements/ThirdQuantity"/>
</ThirdQuantity>
</Measurements>
<xsl:for-each select="Package">
<Package>
<PackageNumber>
<xsl:value-of select="PackageNumber"/>
</PackageNumber>
<PackageKind>
<xsl:value-of select="PackageKind"/>
</PackageKind>
<PackageMarks>
<xsl:value-of select="PackageMarks"/>
</PackageMarks>
<PackageLanguage>
<xsl:value-of select="PackageLanguage"/>
</PackageLanguage>
</Package>
</xsl:for-each>
<PriceValue>
<ItemStatisticalValue>
<xsl:value-of select="PriceValue/ItemStatisticalValue"/>
</ItemStatisticalValue>
<ItemPrice>
<xsl:value-of select="PriceValue/ItemPrice"/>
</ItemPrice>
</PriceValue>
<ItemReferences>
<xsl:for-each select="ItemReferences/ContainerID">
<ContainerID>
<xsl:value-of select="."/>
</ContainerID>
</xsl:for-each>
<QuotaNo>
<xsl:value-of select="ItemReferences/QuotaNo"/>
</QuotaNo>
<UNDangerousGoodsCode>
<xsl:value-of select="ItemReferences/UNDangerousGoodsCode"/>
</UNDangerousGoodsCode>
</ItemReferences>
<GoodsDescription>
<GoodsDescription>
<xsl:value-of select="GoodsDescription/GoodsDescription"/>
</GoodsDescription>
<GoodsDescriptionLanguage>
<xsl:value-of select="GoodsDescription/GoodsDescriptionLanguage"/>
</GoodsDescriptionLanguage>
</GoodsDescription>
<Documents>
<xsl:for-each select="Documents/PreviousDocument">
<PreviousDocument>
<PreviousDocumentKind>
<xsl:value-of select="PreviousDocumentKind"/>
</PreviousDocumentKind>
<PreviousDocumentIdentifier>
<xsl:value-of select="PreviousDocumentIdentifier"/>
</PreviousDocumentIdentifier>
<PreviousDocumentType>
<xsl:value-of select="PreviousDocumentType"/>
</PreviousDocumentType>
<PreviousDocumentLanguage>
<xsl:value-of select="PreviousDocumentLanguage"/>
</PreviousDocumentLanguage>
</PreviousDocument>
</xsl:for-each>
<xsl:for-each select="Documents/ItemDocument">
<ItemDocument>
<DocumentCode>
<xsl:value-of select="DocumentCode"/>
</DocumentCode>
<DocumentPart>
<xsl:value-of select="DocumentPart"/>
</DocumentPart>
<DocumentQuantity>
<xsl:value-of select="DocumentQuantity"/>
</DocumentQuantity>
<DocumentReason>
<xsl:value-of select="DocumentReason"/>
</DocumentReason>
<DocumentReference>
<xsl:value-of select="DocumentReference"/>
</DocumentReference>
<DocumentStatus>
<xsl:value-of select="DocumentStatus"/>
</DocumentStatus>
<DocumentLanguage>
<xsl:value-of select="DocumentLanguage"/>
</DocumentLanguage>
</ItemDocument>
</xsl:for-each>
</Documents>
<Valuation>
<ValuationMethodCode>
<xsl:value-of select="Valuation/ValuationMethodCode"/>
</ValuationMethodCode>
<ItemValuationAdjustmentCode>
<xsl:value-of select="Valuation/ItemValuationAdjustmentCode"/>
</ItemValuationAdjustmentCode>
<ItemValuationAdjustmentPercentage>
<xsl:value-of select="Valuation/ItemValuationAdjustmentPercentage"/>
</ItemValuationAdjustmentPercentage>
</Valuation>
<ItemTransportChargeMOP>
<xsl:value-of select="ItemTransportChargeMOP"/>
</ItemTransportChargeMOP>
<xsl:for-each select="ItemProcessingInstructions">
<ItemProcessingInstructions>
<xsl:value-of select="."/>
</ItemProcessingInstructions>
</xsl:for-each>
</Items>
</xsl:for-each>
<NumberOfPackages>
<xsl:value-of select="/Declaration/Header/NumberOfPackages"/>
</NumberOfPackages>
</Header>
</Declaration>
</xsl:template>
</xsl:stylesheet>
so for source xml
<Declaration>
<Message>
<Meduim>#+#</Meduim>
<MessageIdentifier>AA</MessageIdentifier>
<CommonAccessReference></CommonAccessReference>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<DeclarationCurrency></DeclarationCurrency>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
the final output is
<Declaration>
<Message>
<Meduim></Meduim>
<MessageIdentifier>AA</MessageIdentifier>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
I. Performing a chain of transformations is used quite often in XSLT applications, though doing this entirely in XSLT 1.0 requires the use of the vendor-specific xxx:node-set() function. In XSLT 2.0 no such extension is needed as the infamous RTF datatype is eliminated there.
Here is an example (too-simple to be meaningful, but illustrating completely how this is done):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:variable name="vPass1"
select="ext:node-set($vrtfPass1)"/>
<xsl:apply-templates mode="pass2"
select="$vPass1/*"/>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
the wanted, correct result is produced:
<num>2</num>
<num>6</num>
<num>10</num>
<num>14</num>
<num>18</num>
Explanation:
In the first step the XML document is transformed and the result is defined as the value of the variable $vrtfPass1. This copies only the num elements that have odd value (not even).
The $vrtfPass1 variable, being of type RTF, is not directly usable for XPath expressions so we convert it to a normal tree, using the EXSLT (implemented by most XSLT 1.0 processors) function ext:node-set and defining another variable -- $vPass1 whose value is this tree.
We now perform the second transformation in our chain of transformations -- on the result of the first transformation, that is kept as the value of the variable $vPass1. Not to mess with the first-pass template, we specify that the new processing should be in a named mode, called "pass2". In this mode the value of any num element is multiplied by two.
See also the answer of Michael Kay to your first question, which also explained this general technique.
II. XSLT 2.0 solution (no RTFs):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vPass1" >
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:apply-templates mode="pass2"
select="$vPass1/*"/>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
III. Using the compose() and compose-flist() functions/templates of FXSL
The FXSL library provides two convenient functions/template that support easy chaining of transformations. The former composes two functions/transformations while the latter composes all functions/transformations that are provided in a sequence.
Here is a simple, complete code example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:myFun1="f:myFun1"
xmlns:myFun2="f:myFun2"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="xsl f ext myFun1 myFun2"
>
<xsl:import href="compose.xsl"/>
<xsl:import href="compose-flist.xsl"/>
<!-- to be applied on any xml source -->
<xsl:output method="text"/>
<myFun1:myFun1/>
<myFun2:myFun2/>
<xsl:template match="/">
<xsl:variable name="vFun1" select="document('')/*/myFun1:*[1]"/>
<xsl:variable name="vFun2" select="document('')/*/myFun2:*[1]"/>
Compose:
(*3).(*2) 3 =
<xsl:call-template name="compose">
<xsl:with-param name="pFun1" select="$vFun1"/>
<xsl:with-param name="pFun2" select="$vFun2"/>
<xsl:with-param name="pArg1" select="3"/>
</xsl:call-template>
<xsl:variable name="vrtfParam">
<xsl:copy-of select="$vFun1"/>
<xsl:copy-of select="$vFun2"/>
<xsl:copy-of select="$vFun1"/>
</xsl:variable>
Multi Compose:
(*3).(*2).(*3) 2 =
<xsl:call-template name="compose-flist">
<xsl:with-param name="pFunList" select="ext:node-set($vrtfParam)/*"/>
<xsl:with-param name="pArg1" select="2"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="myFun1:*" mode="f:FXSL">
<xsl:param name="pArg1"/>
<xsl:value-of select="3 * $pArg1"/>
</xsl:template>
<xsl:template match="myFun2:*" mode="f:FXSL">
<xsl:param name="pArg1"/>
<xsl:value-of select="2 * $pArg1"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on any XML document (not used), the wanted, correct results are produced:
Compose:
(*3).(*2) 3 =
18
Multi Compose:
(*3).(*2).(*3) 2 =
36
Pure XSLT 1.0 does not support chaining templates (nor stylesheets as a whole). You can either solve this program outside of XSLT by calling the second xslt template and passing it the output of the first manually, or you can use the fairly pervasive extension function node-set(). MSXML, .NET, EXSL and many other implementations support such a function. The namespace prefix for node-set varies depending on XSLT implementation, but the EXSL prefix is a good bet (and .NET, though undocumented, supports this).
To use node-set store the result of a template in an xsl:variable or xsl:param and do something like <xsl:apply-templates select="exsl:node-set($myvarname)"/>.
Finally, you can of course rewrite your two templates to provide the functionality of both in one pass - but in general, this isn't a trivial thing to do.
I don't understand the problem.
The solution I posted in your last question already works.
For this input:
<?xml version="1.0" encoding="UTF-8"?>
<Declaration>
<Message>
<Meduim>#+#</Meduim>
<MessageIdentifier>AA</MessageIdentifier>
<CommonAccessReference></CommonAccessReference>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<DeclarationCurrency></DeclarationCurrency>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
Output will be:
<?xml version="1.0" encoding="UTF-8"?>
<Declaration>
<Message>
<Meduim/>
<MessageIdentifier>AA</MessageIdentifier>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
You, in fact, don't need your original stylesheet, because basically you just copy the tree.
I have a constant and a variable that I wann mouch together to select a specific node, this is what I want to do:
<xsl:attribute name="value">
<xsl:value-of>
<xsl:attribute name="select">
<xsl:text>/root/meta/url_params/
<xsl:value-of select="$inputid" />
</xsl:attribute>
</xsl:value-of>
</xsl:attribute>
How come it doesn't work, and what could I do instad?
While #Alejandro is right that in the general case dynamic evaluation will be needed (and this may be provided in XSLT 2.1+), there are manageable simpler cases.
For example, if $inputid contains just a name, you probably want this:
<xsl:value-of select="/root/meta/url_params/*[name()=$inputid]"/>
We can implement a rather general dynamic XPath evaluator if we only restrict each location path to be an element name:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:param name="inputId" select="'param/yyy/value'"/>
<xsl:variable name="vXpathExpression"
select="concat('root/meta/url_params/', $inputId)"/>
<xsl:template match="/">
<xsl:value-of select="$vXpathExpression"/>: <xsl:text/>
<xsl:call-template name="getNodeValue">
<xsl:with-param name="pExpression"
select="$vXpathExpression"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="getNodeValue">
<xsl:param name="pExpression"/>
<xsl:param name="pCurrentNode" select="."/>
<xsl:choose>
<xsl:when test="not(contains($pExpression, '/'))">
<xsl:value-of select="$pCurrentNode/*[name()=$pExpression]"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="getNodeValue">
<xsl:with-param name="pExpression"
select="substring-after($pExpression, '/')"/>
<xsl:with-param name="pCurrentNode" select=
"$pCurrentNode/*[name()=substring-before($pExpression, '/')]"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on this XML document:
<root>
<meta>
<url_params>
<param>
<xxx>
<value>5</value>
</xxx>
</param>
<param>
<yyy>
<value>8</value>
</yyy>
</param>
</url_params>
</meta>
</root>
the wanted, correct result is produced:
root/meta/url_params/param/yyy/value: 8
There is no runtime evaluation for XPath expression in standar XSLT 1.0
So, depending what is $inputid, you could have different solutions.
But this /root/meta/url_params/$inputid is wrong because right hand of / must be a relative path in XPath 1.0 (in XPath 2.0 can be a function call, also).
For this particulary case you can use:
/root/meta/url_params/*[name()=$inputid]
or
/root/meta/url_params/*[#id=$inputid]
For a general case, I will go with walker pattern like Dimitre's answer.