XSL key using multiple values - xslt

The following is the sample XML structure I'm working on:
<command name="test">
<parameter index="2">4000</parameter>
<tag>4000</tag>
<parameter index="3">tag</parameter>
<parameter index="4">4000</parameter>
</command>
<command name="test">
<parameter index="2">4000</parameter>
<add>
<parameter index="1">ports</parameter>
<parameter index="2">1:1,</parameter>
<parameter index="3">3:1,</parameter>
<parameter index="4">3:9-12,</parameter>
<parameter index="5">4:12</parameter>
</add>
<parameter index="3">add</parameter>
<parameter index="4">ports</parameter>
<parameter index="5">1:1,</parameter>
<parameter index="6">3:1,</parameter>
<parameter index="7">3:9-12,</parameter>
<parameter index="8">4:12</parameter>
<tagged />
<parameter index="9">tagged</parameter>
</command>
And the code snippet on the XSL file is:
<xsl:key name="key" match="command[#name='test'][count(tag) > 0]" use="parameter[#index='2']"/>
<xsl:key name="port" match="command[#name='test'][count(add) > 0]" use="add/parameter"/>
<xsl:template match="xyz">
<xsl:variable name="portid" select="concat($slot-no,concat(':',$port-no))"/>
<xsl:apply-templates select="key('port',$portid)"/>
</xsl:template>
<xsl:template match="command[#name='test']">
<xsl:variable name="name" select="parameter[#index=2]"/>
<object>
<name><xsl:value-of select="$name"/></name>
<class>XYZ</class>
<attributes>
<attribute>
<name>XYZ1</name>
<value><xsl:value-of select="key('key',$name)/tag"/></value>
</attribute>
</attributes>
</object>
</xsl:template>
The variable 'portid' is in the form 'x:x', where x is a number. For each of the portid, I need to associate with the <parameter index="2"> value. Previously we had only one portid value under the <add> node and the solution was working fine.
Now, I need to change the 'use' expression in the XSL key 'port' so that the values are changed from '1:1,' to '1:1' and similarly '3:1,' to '3:1' and expand '3:9-12,' to '3:9' , '3:10' , '3:11' , '3:12' and store them with the value in <parameter index="2">. For example, each time the 'portid' is any one of this '1:1', '3:1', '3:9' , '3:10' , '3:11', '3:12' and '4:12', the value to associate is '4000'.
Is this possible? I'm working on this for a week and still not able to find a solution. Any help would be really appreciated. Thanks a lot guys.

I think you can only do that cleanly with XSLT 2.0 e.g.
<xsl:key name="port" match="command[#name='test'][add]" use="add/parameter/replace(., ',', '')"/>
will do for the simply replacement, for the more complex one you will probably have to write a function with xsl:function that takes e.g. '3:9-12,' and returns the sequence you want, that shouldn't be to difficult with XPath 2.0's string functions.

I was able to find the solution for this problem by not using the XSL key. Instead I used a call-template method to strip the commas and expand the series and find the match. Thanks to all who cared to help me on this

Related

Is there a way to iterate the xml element in wso2 6.5.0

Please someone could help. I have a set of data as csv(from excel multiple sheets i have formed csv)just i want to insert those data into multiple table depends the sheets of an excel.
please help me to sort out my issues.
I expected those csv in each iteration to form xml.
First, we can build the XML from CSV data and iterate through the XML. Please find a sample config below. In this sample, it will pick the CSV files from the source directory and process.
Smooks Config:
<?xml version="1.0"?>
<smooks-resource-list
xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.2.xsd">
<resource-config selector="org.xml.sax.driver">
<resource>org.milyn.csv.CSVReader</resource>
<param name="fields">firstname,lastname,gender,age,country</param>
<param name="rootElementName">people</param>
<param name="recordElementName">person</param>
</resource-config>
</smooks-resource-list>
Proxy:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="CSVToXML"
transports="https,http,vfs"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<smooks config-key="conf:/repository/smooks-config.xml">
<input type="text"/>
<output type="xml"/>
</smooks>
<!-- Here iterate through the XML -->
</inSequence>
<outSequence/>
</target>
<parameter name="transport.PollInterval">1000</parameter>
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="Operation">urn:placeOrder</parameter>
<parameter name="transport.vfs.FileURI">file://<SOURCE_DIR></parameter>
<parameter name="transport.vfs.MoveAfterProcess">file://<PROCESSED_FILES_DIR></parameter>
<parameter name="transport.vfs.MoveAfterFailure">file://<FAILED_FILES_DIR></parameter>
<parameter name="transport.vfs.FileNamePattern">.*\.csv</parameter>
<parameter name="transport.vfs.ContentType">text/plain</parameter>
<parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
<description/>
</proxy>
References:
1. https://docs.wso2.com/display/EI640/VFS+Transport
2. https://docs.wso2.com/display/EI640/Smooks+Mediator
3. https://docs.wso2.com/display/EI640/Iterate+Mediator

WSO2 Integrator 6, File inbound Protocol process code

Currently working for a company on wso2 integrator, I need to retrieve files periodically created into a directory so that they can be processed, modified and sent to a remote API.
The problem is that we need to use wso2 exclusively and absolutely can't code side programs to adapt to the situation. We can use script though only if they are embedded within wso2.
Does someone have a clue?
This is a simple synapse configuration that:
Wait for incoming CSV files on a given directory
Convert its contents to XML
Do some transformation on its elements
Sends the result to a another endpoint (an output directory in this case)
I hope it helps to get you going (comments inline):
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- ======================================== -->
<!-- Smooks configuration to parse sample CSV -->
<!-- ======================================== -->
<localEntry key="smooks-orders-csv">
<smooks-resource-list
xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.2.xsd">
<resource-config selector="org.xml.sax.driver">
<resource>org.milyn.csv.CSVReader</resource>
<param name="fields">OrderId,SKU,Quantity,UnitPrice,TotalPrice</param>
<param name="skip-line-count">1</param> <!-- Skip Header line -->
<param name="rootElementName">orders</param>
<param name="recordElementName">order</param>
</resource-config>
</smooks-resource-list>
</localEntry>
<!-- ====================================================== -->
<!-- XML processing logic: Replaces SKU number 0002 to 0003 -->
<!-- ====================================================== -->
<localEntry key="change-sku">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SKU/text()[.='0002']">0003</xsl:template>
</xsl:stylesheet>
<description/>
</localEntry>
<!-- *********************** -->
<!-- Process Orders sequence -->
<!-- *********************** -->
<sequence name="process_orders" onError="fault" statistics="enable" trace="enable">
<!-- Convert incoming file into a stream of orders -->
<smooks config-key="smooks-orders-csv">
<input type="text"/>
<output type="xml"/>
</smooks>
<!-- General Synapse properties that must be set for a One-Way exchange pattern -->
<property name="FORCE_SC_ACCEPTED" scope="axis2" value="true"/>
<property name="OUT_ONLY" value="true"/>
<!-- VFS send will fail unless you remove this property -->
<property action="remove" name="ClientApiNonBlocking" scope="axis2"/>
<!-- The "magic" property 'transport.vfs.ReplyFileName' is used by the VFS transport to define output file name
when the specified URI is a directory
-->
<property
expression="fn:concat(fn:substring-after(get-property('MessageID'), 'urn:uuid:'), '.xml')"
name="transport.vfs.ReplyFileName" scope="transport" xmlns:ns="http://org.apache.synapse/xsd"/>
<!-- Create output file -->
<send>
<endpoint>
<address format="pox" uri="vfs:file:///mnt/c/transfer/out"/>
</endpoint>
</send>
</sequence>
<!-- Inbound polling endpoint -->
<inboundEndpoint name="received_orders" onError="fault"
protocol="file" sequence="process_orders" suspend="false">
<parameters>
<parameter name="interval">1000</parameter>
<parameter name="sequential">true</parameter>
<parameter name="coordination">true</parameter>
<!-- Input directory -->
<parameter name="transport.vfs.FileURI">file:///mnt/c/transfer/in</parameter>
<!-- CSV files are plain text messages -->
<parameter name="transport.vfs.ContentType">text/plain</parameter>
<!-- RegExp used to filter files in input directory -->
<parameter name="transport.vfs.FileNamePattern">.*\.txt</parameter>
<parameter name="transport.vfs.Locking">disable</parameter>
<!-- Move processed files to the 'processed' subdirectory -->
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="transport.vfs.MoveAfterProcess">file:///mnt/c/transfer/in/processed</parameter>
<!-- Move failed files to the 'rejected subdirectory -->
<parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
<parameter name="transport.vfs.MoveAfterFailure">file:///mnt/c/transfer/in/rejected</parameter>
<parameter name="transport.vfs.AutoLockRelease">true</parameter>
<parameter name="transport.vfs.LockReleaseSameNode">false</parameter>
<parameter name="transport.vfs.DistributedLock">false</parameter>
<parameter name="transport.vfs.FileSortAttribute">NONE</parameter>
<parameter name="transport.vfs.FileSortAscending">true</parameter>
<parameter name="transport.vfs.CreateFolder">true</parameter>
<parameter name="transport.vfs.Streaming">false</parameter>
<parameter name="transport.vfs.Build">false</parameter>
</parameters>
</inboundEndpoint>
</definitions>

Storing invalid format of XML in active MQ

I am stuck on below,
I have set content type as XML in my proxy.
As below:
<parameter name="transport.jms.ContentType">
<rules xmlns="">
<jmsProperty>contentType</jmsProperty>
<default>application/xml</default>
</rules>
</parameter>
Sending below message into the queue which is correct one
<Data>
<name>abc</name>
<account>1212</account>
</Data>
But if any tag is missing in it as below. I dont want lose that message instead I want it to store in one special queue
<Data>
<name>abc
<account>1212</account>
Any guidance will be appreciated.Thanks

WSO2 inbound endpoint using registry entry

I am trying to set up an inbound endpoint in ESB 5.0.0. This works fine when setting a fixed value for the file uri. But i am not able to set this with a registry value.
In this question someone asked almost the same.
The answer is about setting <parameter name="transport.vfs.FileURI" key="conf:/repository/esb/esb-configurations/test"/>, but it does not explain what type of registry entry you need to have for a file endpoint.
Can someone give me a full explanation on how to set up a inbound endpoint with a fileuri that is defined in the registry?
The xml of the inbound endpoint
<?xml version="1.0" encoding="UTF-8"?>
<inboundEndpoint name="Poller.Label.Print.NL"
onError="FaultSequenceEmail" protocol="file" sequence="LabelPrint"
suspend="false" xmlns="http://ws.apache.org/ns/synapse">
<parameters>
<parameter name="interval">1000</parameter>
<parameter name="sequential">true</parameter>
<parameter name="coordination">true</parameter>
<parameter name="transport.vfs.ContentType">text/plain</parameter>
<parameter name="transport.vfs.LockReleaseSameNode">false</parameter>
<parameter name="transport.vfs.AutoLockRelease">false</parameter>
<parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="transport.vfs.FileURI">conf:/test</parameter>
<parameter name="transport.vfs.MoveAfterFailure">file:///c:\tdemo\error</parameter>
<parameter name="transport.vfs.MoveTimestampFormat">yyyyMMddHHmmss</parameter>
<parameter name="transport.vfs.DistributedLock">false</parameter>
<parameter name="transport.vfs.FileNamePattern">.*.dd</parameter>
<parameter name="transport.vfs.FileProcessInterval">10</parameter>
<parameter name="transport.vfs.MoveAfterProcess">file:///c:\demo\archive</parameter>
<parameter name="transport.vfs.Locking">disable</parameter>
<parameter name="transport.vfs.FileSortAttribute">lastmodifiedtimestamp</parameter>
<parameter name="transport.vfs.FileSortAscending">true</parameter>
<parameter name="transport.vfs.CreateFolder">false</parameter>
<parameter name="transport.vfs.Streaming">true</parameter>
<parameter name="transport.vfs.Build">false</parameter>
</parameters>
</inboundEndpoint>
tested with the following xml, but did not work:
<?xml version="1.0" encoding="UTF-8"?>
<localEntry xmlns="ws.apache.org/ns/synapse" key="test">
file:///c:/demo/
</localEntry>
The file store in conf:/test need to have this content:
file:///c:\demo\
Check this:

why is services.xml not valid?

<service name="CaseCreate" >
<Description>
Please Type your service description here
</Description>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<parameter name="ServiceClass" locked="false">casecreate.CaseCreate</parameter>
<parameter name="InflowSecurity">
<action>
<items>UsernameToken</items>
<passwordCallbackClass>com.myproject.authentication.PWCBHandler</passwordCallbackClass>
</action>
</parameter>
<module ref="rampart" />
</service>
Above is the services.xml that I am trying to use, but eclipse is telling me that this is not a valid sevices.xml file. When I remove the parameter with name="InflowSevcurity" Eclipse does not complain. Does anyone know why?