WSO2 Enrich array - wso2

I'm using WSO2 ESB (4.8.1) and I need transform this payload:
[
{
"id":"1",
"budget":"a"
},
{
"id":"2",
"bidget:"b"
}
]
in this one using enrich mediator (if it's possible):
[
{
"id":"1",
"budget":"a",
"result":"1-a"
},
{
"id":"2",
"bidget:"b",
"result":"2-b"
}
]
Any suggestion?
Thanks in advance

Take a look a this sample:
Input file:
<?xml version="1.0" encoding="UTF-8" ?>
<employees>
<root>
<id>1</id>
<budget>a</budget>
</root>
<root>
<id>2</id>
<budget>b</budget>
</root>
<root>
<id>3</id>
<budget>c</budget>
</root>
</employees>
My xslt:
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<employees>
<xsl:for-each select="employees/root">
<root>
<id>
<xsl:value-of select="id"/>
</id>
<budget>
<xsl:value-of select="budget"/>
</budget>
<result>
<xsl:value-of select="concat(id,'-',budget)"/>
</result>
</root>
</xsl:for-each>
</employees>
</xsl:template>
</xsl:stylesheet>
Output file:
<?xml version="1.0" encoding="UTF-8" ?>
<employees>
<root>
<id>1</id>
<budget>a</budget>
<result>1-a</result>
</root>
<root>
<id>2</id>
<budget>b</budget>
<result>2-b</result>
</root>
<root>
<id>3</id>
<budget>c</budget>
<result>3-c</result>
</root>
</employees>
So you can use an xslt mediator in WSO2 ESB(https://docs.wso2.com/display/ESB490/XSLT+Mediator ) and this configuration or similar and work with your definitions.
Regards.

I think when you don't know about the length of array you con't transform it with enrich or payloadFactory. I found same problem in WSO2 ESB document. this JS function transform an array of objects.
function transform(mc) {
payload = mc.getPayloadJSON();
results = payload.results;
var response = new Array();
for (i = 0; i < results.length; ++i) {
location_object = results[i];
l = new Object();
l.name = location_object.name;
l.tags = location_object.types;
l.id = "ID:" + (location_object.id);
response[i] = l;
}
mc.setPayloadJSON(response);
}
See scipte mediator in this link for more information.

Related

XML To Text through XSLT

This is the original xml file
<?xml version="1.0" encoding="utf-8"?>
<Report xsi:schemaLocation="FPPD2_AL2.srdl http://sunserver/ReportServer?%2FSunSystems%2FExample%20Reports%2FProcess%2FFPPD2_AL2.srdl&rs%3AFormat=XML&rc%3ASchema=True" Name="FPPD2_AL2.srdl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="FPPD2_AL2.srdl">
<Detail_2_1>
<Detail_2_1_Group_Collection>
<Item RowNumber="1" transactionDate="2019-11-04" description_1="PI -Local" BankSortCode="" transactionReference="T0004" DebitCredit_Description="Credit" baseAmount_baseCreditAmount="236.32" baseAmount_baseDebitAmount="0.00" baseAmount_amount_10="-236.32" SupBankAccountName="C Voice Bank Account" TransactionAmount_TransactionCreditAmount="-413.56" TransactionAmount_Amount="-413.56" CurrencyCode_3="USD" baseAmount_amount_1="236.32" SupBankAccountNumber="01234567" SupBankSortCode="123456" DebitCredit_Code="C" ReportingAmount_ReportingCreditAmount="-413.56" ReportingAmount_ReportingDebitAmount="0.00" BankProcessDate_1="20191106" AccountCode_1="CVOI001" ProfileCode_param="BACS">
<subreport>
<Report Name="FPPD2_s1.srdl">
<Detail_2_1>
<Detail_2_1_Group_Collection>
<Item PaymentAccount="52100" BankAccountName="Own Bank Account" BankAccountNumber="0011223344" />
</Detail_2_1_Group_Collection>
</Detail_2_1>
</Report>
</subreport>
</Item>
</Detail_2_1_Group_Collection>
</Detail_2_1>
</Report>
I was trying to get the value of the PaymentAccount ("52100"). Here;s my code so far, but it does not return anything
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="FPPD2_AL2.srdl"
xmlns:sr1="FPPD2_s1.srdl">
<xsl:output method="text"/>
<xsl:template match="ns2:Report">
<xsl:value-of select="ns2:Detail_2_1/ns2:Detail_2_1_Group_Collection/ns2:Item/ns2:subreport/ns2:Report/ns2:Detail_2_1/ns2:Detail_2_1_Group_Collection/Item[Name='PaymentAccount']"/>
</xsl:template>
</xsl:stylesheet>
I am pretty new to XSLT so I don't know if there is anything wrong with my syntax or structure?
Thank you
Instead of:
.../Item[Name='PaymentAccount']
use:
.../ns2:Item/#PaymentAccount

xslt date conversion to UTC

I am very new to xslt programming. Can any one help with this:
input xml:
<?xml version="1.0" encoding="UTF-8"?>
<MESSAGE>
<ER>
<MXITEMOUT xmlns="http://www.mro.com/mx/integration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="EN">
<Header operation="Notify" event="1">
<SenderID type="MAXIMO" majorversion="6" minorversion="0" build="02" dbbuild="V600-76">MX</SenderID>
<CreationDateTime>2005-08-15T14:28:06-05:00</CreationDateTime>
<RecipientID>EXTSYS1234</RecipientID>
<MessageID>1124</MessageID>
</Header>
<Content>
<MXITEM>
<ITEM action="Add">
<ITEMNUM>I1001</ITEMNUM>
<DESCRIPTION langenabled="1">test item</DESCRIPTION>
<ROTATING>1</ROTATING>
<LOTTYPE maxvalue="NOLOT">NOLOT</LOTTYPE>
<CAPITALIZED>0</CAPITALIZED>
<CREATEDDATE>2014-05-22T13:00:46+10:00</CREATEDDATE>
</ITEM>
</MXITEM>
</Content>
</MXITEMOUT>
</ER>
<IR>
<MXITEMOUT xmlns="http://www.mro.com/mx/integration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="EN">
<Header operation="Notify" event="1">
<SenderID type="MAXIMO" majorversion="6" minorversion="0" build="02" dbbuild="V600-76">MX</SenderID>
<CreationDateTime>2005-08-15T14:28:06-05:00</CreationDateTime>
<RecipientID>EXTSYS1234</RecipientID>
<MessageID>1124</MessageID>
</Header>
<Content>
<MXITEM>
<ITEM action="Add">
<ITEMNUM>I1001</ITEMNUM>
<DESCRIPTION langenabled="1">test item</DESCRIPTION>
<ROTATING>1</ROTATING>
<LOTTYPE maxvalue="NOLOT">NOLOT</LOTTYPE>
<CAPITALIZED>0</CAPITALIZED>
<CREATEDDATE>2014-05-22T13:00:46+10:00</CREATEDDATE>
</ITEM>
</MXITEM>
</Content>
</MXITEMOUT>
</IR>
</MESSAGE>
My XSLT is:
<?xml version="1.0"?>
<!--
This XSL is supposed to change the ITEMNUM tag value by prepending 001 to the existing value.
It also strips off the MESSAGE and IR wrapper tags so that the resultant data is consistent with
our XML schema
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mro="http://www.mro.com/mx/integration" version="1.0" exclude-result-prefixes="mro">
<xsl:template match="/MESSAGE">
<xsl:apply-templates select="IR"/>
</xsl:template>
<xsl:template match="IR">
<xsl:apply-templates select="#*|*|text()"/>
</xsl:template>
<xsl:template match="#*|*|text()">
<xsl:copy>
<xsl:apply-templates select="#*|*|text()"/>
</xsl:copy>
</xsl:template>
<!--
Change the ITEMNUM tag value by prepending 001 to the existing value
-->
<xsl:template match="mro:ITEMNUM">
<xsl:element name="ITEMNUM" namespace="http://www.mro.com/mx/integration">
<xsl:text>MAX-</xsl:text><xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Current output is:
<?xml version="1.0" encoding="UTF-8"?>
<MXITEMOUT xmlns="http://www.mro.com/mx/integration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="EN">
<Header operation="Notify" event="1">
<SenderID type="MAXIMO" majorversion="6" minorversion="0" build="02" dbbuild="V600-76">MX</SenderID>
<CreationDateTime>2005-08-15T14:28:06-05:00</CreationDateTime>
<RecipientID>EXTSYS1234</RecipientID>
<MessageID>1124</MessageID>
</Header>
<Content>
<MXITEM>
<ITEM action="Add">
<mro:ITEMNUM xmlns:mro="http://www.mro.com/mx/integration">MAX-I1001</mro:ITEMNUM>
<DESCRIPTION langenabled="1">test item</DESCRIPTION>
<ROTATING>1</ROTATING>
<LOTTYPE maxvalue="NOLOT">NOLOT</LOTTYPE>
<CAPITALIZED>0</CAPITALIZED>
<CREATEDDATE>2014-05-22T13:00:46+10:00</CREATEDDATE>
</ITEM>
</MXITEM>
</Content>
</MXITEMOUT>
Expected output is:
<?xml version="1.0" encoding="UTF-8"?>
<MXITEMOUT xmlns="http://www.mro.com/mx/integration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="EN">
<Header operation="Notify" event="1">
<SenderID type="MAXIMO" majorversion="6" minorversion="0" build="02" dbbuild="V600-76">MX</SenderID>
<CreationDateTime>2005-08-15T14:28:06-05:00</CreationDateTime>
<RecipientID>EXTSYS1234</RecipientID>
<MessageID>1124</MessageID>
</Header>
<Content>
<MXITEM>
<ITEM action="Add">
<mro:ITEMNUM xmlns:mro="http://www.mro.com/mx/integration">MAX-I1001</mro:ITEMNUM>
<DESCRIPTION langenabled="1">test item</DESCRIPTION>
<ROTATING>1</ROTATING>
<LOTTYPE maxvalue="NOLOT">NOLOT</LOTTYPE>
<CAPITALIZED>0</CAPITALIZED>
<CREATEDDATE>2014-05-22T23:00:46.000Z</CREATEDDATE>
</ITEM>
</MXITEM>
</Content>
</MXITEMOUT>
I am trying find logic in google to convert date to utc format in xslt.
It is throwing strange errors.
XML date:2014-05-22T13:00:46+10:00 Expected Date: 2014-05-22T23:00:46.000Z

Two phase XSLT transformation converting string to XML first

I have the following XML:
<?xml version="1.0" encoding="utf-8"?>
<string>
<Table>
<Rows>
<Row Id="0">
<Column Name="INS_NAME" XPath="Ins.Name">Jane</Column>
<Column Name="INS_LASTNAME" XPath="Ins.LastName">Smith</Column>
</Row>
<Row Id="1">
<Column Name="INS_NAME" XPath="Ins.Name">Joe</Column>
<Column Name="INS_LASTNAME" XPath="Ins.LastName">Miller</Column>
</Row>
<Row Id="2">
<Column Name="INS_NAME" XPath="Ins.Name">George</Column>
<Column Name="INS_LASTNAME" XPath="Ins.LastName">Ramsey</Column>
</Row>
</Rows>
</Table>
</string>
and I would like to transform it to this XML using a single XSLT:
<?xml version="1.0" encoding="utf-8"?>
<Customers>
<Customer><Name>Jane</Name><LastName>Smith</LastName></Customer>
<Customer><Name>Joe</Name><LastName>Miller</LastName></Customer>
<Customer><Name>George</Name><LastName>Ramsey</LastName></Customer>
</Customers>
I can do it with two different XSLT's:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="/" disable-output-escaping="yes" />
</xsl:template>
</xsl:stylesheet>
and then:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Customers>
<xsl:for-each select="Table/Rows/Row">
<Customer>
<Name><xsl:value-of select="Column[#Name='INS_NAME']" /></Name>
<LastName><xsl:value-of select="Column[#Name='INS_LASTNAME']" /></LastName>
</Customer>
</xsl:for-each>
</Customers>
</xsl:template>
</xsl:stylesheet>
I have been reading about multi phase transformations but I can't seem to get it. I have tried saving the first XSLT in a variable but it seems disable-output-escaping="yes" does not work when saving to a variable.
Can anybody help?
Thank you.
New information (Edit)
I am now translating the string this way:
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="stringXml">
<?xml version="1.0" encoding="utf-8"?>
<xsl:value-of select="translate(translate(/,'>','>'),'<','<')" />
</xsl:variable>
...
How can I do a transformation on the resulting XML stored in stringXML?
Final Solution (Edit)
<msxml:script implements-prefix="myLib" language="C#">
<msxml:assembly name="System.Web"/>
<msxml:using namespace="System.Web"/>
<![CDATA[
public System.Xml.XPath.XPathNodeIterator convertText(string text)
{
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.LoadXml(text);
return doc.CreateNavigator().Select("/");
}
]]>
</msxml:script>
it seems disable-output-escaping="yes" does not work when saving to a
variable.
Your observation is correct.
DOE only affects the serialization of the (final) result of the transformation and isn't applied on intermediary trees.
Here is what the W3C XSLT 1.0 specification explicitly says:
"An XSLT processor will only be able to disable output escaping if it
controls how the result tree is output. This may not always be the
case. For example, the result tree may be used as the source tree for
another XSLT transformation instead of being output."
The same negative answer holds for trying to use a variable, whose value is a string, containing a textual representation of an XML document.
I had a similar situation where I needed to parse an escaped XML inside my actual XML. I will post up my solution to also help someone else. Please also note that I am also using Saxon-PE parser.
In my situation I have the original XML that contains an escaped XML in a child node. I needed to get the inner XML inside the RootNode of the escaped XML.
Source XML:
<?xml version="1.0" encoding="utf-8"?>
<MyTestXml>
<SomeXmlStuff>
<Text1>Hello</Text1>
<Text2>World</Text2>
</SomeXmlStuff>
<SomeEscapedXml><RootNode><FirstNode>Hello</FirstNode><SecondNode>World</SecondNode><ThirdNode>Again</ThirdNode></RootNode></SomeEscapedXml>
</MyTestXml>
When you unescaped the XML, it looks like this:
<RootNode>
<FirstNode>Hello</FirstNode>
<SecondNode>World</SecondNode>
<ThirdNode>Again</ThirdNode>
</RootNode>
With the following XSLT transformation is applied on the source XML:
<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://saxon.sf.net/"
exclude-result-prefixes="xsl saxon">
<xsl:template match="/">
<MyOutput>
<xsl:call-template name="GetRootNodeInnerXml">
<xsl:with-param name="escapedXml" select="MyTestXml/SomeEscapedXml" />
</xsl:call-template>
</MyOutput>
</xsl:template>
<xsl:template name="GetRootNodeInnerXml">
<xsl:param name="escapedXml" required="yes" />
<xsl:copy-of select="saxon:parse($escapedXml)/RootNode/node()"/>
<!-- You can also use this line below if you're not using saxon parser. Just make sure your parser supports XSL 3.0 -->
<!--
<xsl:copy-of select="fn:parse-xml($escapedXml)/RootNode/node()" xmlns:fn="http://www.w3.org/2005/xpath-functions"/>
-->
</xsl:template>
</xsl:stylesheet>
This gives you the following output:
<?xml version='1.0' ?>
<MyOutput>
<FirstNode>Hello</FirstNode>
<SecondNode>World</SecondNode>
<ThirdNode>Again</ThirdNode>
</MyOutput>

exclude empty elements

in my sample xml file, i have this:
<AAA mandatory = "true"> good </AAA>
<BBB mandatory = "true"></BBB>
<CCC />
in the resulting xml, the result should be like this:
<AAA> good </AAA>
<BBB></BBB>
what should i put in my transformation file xslt to produce this xml?
currently, i have this:
<xsl:template match="node()[(#mandatory='true' or (following-sibling::*[#mandatory='true' and string-length(normalize-space(.)) > 0] or preceding-sibling::*[#mandatory='true' and string-length(normalize-space(.)) > 0])) or descendant-or-self::*[string-length(normalize-space(.)) > 0]]">
but this keeps displaying
<CCC />
When I run your XSLT on the input XML I do not get any output.
Your provided XML is not well formed and the XPATH in your "match" is too complicated I think.
I came up with a XSL 1.0 solution but I do not know if you can use that in XSL 2.0. I do not have experience with XSL 2.0.
This XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<list>
<xsl:apply-templates/>
</list>
</xsl:template>
<xsl:template match="*[#mandatory='true']">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
applied to this input XML:
<?xml version="1.0" encoding="UTF-8"?>
<list>
<AAA mandatory="true"> good </AAA>
<BBB mandatory="true"/>
<CCC/>
</list>
gives this output XML:
<?xml version="1.0" encoding="UTF-8"?>
<list>
<AAA> good </AAA>
<BBB/>
</list>
I am not sure if you also want to check on the text length of an element or only on the attribute mandatory. I only check on the attribute in my XSL.

calling function with xslt using xpath selection

How can I call javascript/c# function in xslt passing xpath selection value.
Here is how I call function with manualy typed parameter:
<xsl:value-of select="cs:my('some text')"/>
Here is an example from the MSXML 4 SDK (this should be the same for MSXML 6, and is quite similar for .NEt's XslCompiledTransform -- for the latter search MSDN for <msxsl:script>)
Example This example defines a script block with a namespace
prefix of user that contains a function called xml that takes a
node-list as an argument. Later, this function, xml(nodelist) in the
user namespace, is called from the select attribute of .
XML File (customers.xml)
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="script.xsl" ?>
<customers>
<customer>
<name>John Smith</name>
<address>123 Elm St.</address>
<phone>(123) 456-7890</phone>
</customer>
<customer>
<name>Mary Jones</name>
<address>456 Oak Ave.</address>
<phone>(156) 789-0123</phone>
</customer>
</customers>
XSLT File (script.xsl)
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://mycompany.com/mynamespace">
<msxsl:script language="JScript" implements-prefix="user">
function xml(nodelist) {
return nodelist.nextNode().xml;
}
</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:xml(.)"/>
</xsl:template>
</xsl:stylesheet>
Formatted Output
<?xml version="1.0" encoding="UTF-16"?><?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="script.xsl" ?>
<customers>
<customer>
<name>John Smith</name>
<address>123 Elm St.</address>
<phone>(123) 456-7890</phone>
</customer>
<customer>
<name>Mary Jones</name>
<address>456 Oak Ave.</address>
<phone>(156) 789-0123</phone>
</customer>
</customers>