One XML converted into multiple XML in Mule - xslt

I have one xml file like below.
<?xml version='1.0' encoding='UTF-8'?>
<machineDetail>
<machineData>
<machineNumber>00000001</machineNumber>
<concessionUnitType>NONE</concessionUnitType>
<machineType>SCHAERER</machineType>
<customerNumber>69990005</customerNumber>
<equipmentLocation>REM</equipmentLocation>
<installedDate>2013-08-01T00:00:00.000+0000</installedDate>
</machineData>
<machineData>
<machineNumber>00001024</machineNumber>
<concessionUnitType>NONE</concessionUnitType>
<machineType>IBS4</machineType>
<customerNumber>69990005</customerNumber>
<equipmentLocation>1024</equipmentLocation>
<installedDate>2011-09-29T00:00:00.000+0000</installedDate>
</machineData>
</machineDetail>
Now I have to divide into 2 xmls having data like
1.xml
<?xml version='1.0' encoding='UTF-8'?>
<machineDetail>
<machineData>
<machineNumber>00000001</machineNumber>
<concessionUnitType>NONE</concessionUnitType>
<machineType>SCHAERER</machineType>
<customerNumber>69990005</customerNumber>
<equipmentLocation>REM</equipmentLocation>
<installedDate>2013-08-01T00:00:00.000+0000</installedDate>
</machineData>
</machineDetail>
2.xml
<?xml version='1.0' encoding='UTF-8'?>
<machineDetail>
<machineData>
<machineNumber>00001024</machineNumber>
<concessionUnitType>NONE</concessionUnitType>
<machineType>IBS4</machineType>
<customerNumber>69990005</customerNumber>
<equipmentLocation>1024</equipmentLocation>
<installedDate>2011-09-29T00:00:00.000+0000</installedDate>
</machineData>
</machineDetail>
This has to be completed in Mule. Please suggest the xslt in this case. I am a new guy in Mule.

The following flow should do what you asked for. You might need to do cleanup the namespaces if needed..
<mule xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd">
<mulexml:xslt-transformer name="xslt">
<mulexml:xslt-text>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="">
<xsl:output method="xml"/>
<xsl:template match="/">
<machineDetail>
<xsl:copy-of select="." />
</machineDetail>
</xsl:template>
</xsl:stylesheet>
</mulexml:xslt-text>
</mulexml:xslt-transformer>
</mulexml:xslt-transformer>
<file:file-to-string-transformer name="File_to_String"
doc:name="File to String" />
<flow name="testflowsFlow">
<file:inbound-endpoint path="C:\Temp\mule\in"
responseTimeout="10000" doc:name="File" />
<file:file-to-string-transformer
doc:name="File to String" />
<splitter expression="#[xpath('//machineData')]" doc:name="Splitter"
enableCorrelation="ALWAYS" />
<mulexml:dom-to-xml-transformer
doc:name="DOM to XML" />
<file:outbound-endpoint transformer-refs="xslt"
path="C:\Temp\mule\out" responseTimeout="10000" doc:name="File"
outputPattern="#[message.outboundProperties.MULE_CORRELATION_SEQUENCE].xml" />
</flow>

Use a splitter in conjuction with an xpath MEL expression: like so:
<splitter expression="#[xpath('//machineDetail/machineData')]" doc:name="Splitter"/>
This will create two XML document like so:
<machineData>
<machineNumber>00001024</machineNumber>
<concessionUnitType>NONE</concessionUnitType>
<machineType>IBS4</machineType>
<customerNumber>69990005</customerNumber>
<equipmentLocation>1024</equipmentLocation>
<installedDate>2011-09-29T00:00:00.000+0000</installedDate>
</machineData>
Then while the message is split use XSLT or similar to wrap the XML in an
machineDetail element

Related

Extract XML Multiple Namespace with XSL

I have this XML with namespace and i need to extract on segment "NewDataSet"
I have a xsl code but it's not works
<?xml version="1.0" encoding="UTF-8"?>
<Listado_OrdenesResponse xmlns='http://tempuri.org/' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<Listado_OrdenesResult>
<diffgr:diffgram xmlns:diffgr='urn:schemas-microsoft-com:xml-diffgram-v1' xmlns:msdata='urn:schemas-microsoft-com:xml-msdata'>
<NewDataSet xmlns=''>
<RowNum diffgr:id='RowNum1' msdata:rowOrder='0'>
<MATNR>10000101</MATNR> <AUFNR>731200000047</AUFNR>
<MENGE>385</MENGE>
<MEINS>G</MEINS>
</RowNum>
<RowNum diffgr:id='RowNum2' msdata:rowOrder='1'>
<MATNR>45000528</MATNR>
<AUFNR>731200000047</AUFNR>
<MENGE>540</MENGE>
<MEINS>KG</MEINS>
</RowNum>
</NewDataSet>
</diffgr:diffgram>
</Listado_OrdenesResult>
</Listado_OrdenesResponse>
I need to extract like this segment , NewDataSet.
<NewDataSet> <RowNum>
<MATNR>10000101</MATNR>
<AUFNR>731200000047</AUFNR>
</RowNum>
<RowNum>
<MATNR>45000528</MATNR>
<AUFNR>731200000047</AUFNR>
</RowNum>
</NewDataSet>
<!-- Need To Extract -->
I have this code but the return is not as expected.
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid Studio 2018 (https://www.liquid-technologies.com) -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="//NewDataSet">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
When I run the above XSL, I got this XML.
I will have the segment without namespace
<?xml version="1.0" encoding="UTF-8"?>
<RowNum xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diffgr:id="RowNum1"
msdata:rowOrder="0">
<MATNR>10000101</MATNR>
<AUFNR>731200000047</AUFNR>
<MENGE>385</MENGE>
<MEINS>G</MEINS>
</RowNum>
<RowNum xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diffgr:id="RowNum2"
msdata:rowOrder="1">
<MATNR>45000528</MATNR>
<AUFNR>731200000047</AUFNR>
<MENGE>540</MENGE>
<MEINS>KG</MEINS>
</RowNum>
Can you Help me?
In XSLT 2.0, use <xsl:copy-of select="XXXX" copy-namespaces='no'/>.
In XSLT 1.0 you need to use a variant of the identity template, copying elements using <xsl:element name="{local-name()}" namespace="namespace-uri()"/>.
Please don't ask XSLT questions without saying which version you are using, as many things are easier with XSLT 2.0 or 3.0!

Removing xmlns, SOAP:Envelope, SOAP:Body, from xml using XSLT

I am using XSLT to transform the xml response in my project.I have the following xml.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Body>
<response:performJobResponse xmlns:response="http://tempuri.org/" SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<whiteboard>
<PQ>
<SOAP:Envelope SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Body>
<response:performJobResponse SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<whiteboard>
<PQ>
<SOAP:Envelope SOAP:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP:Body>
<performJob loadfromcache="yes">
<jobName>PQIssueUpdate</jobName>
<whiteboard>
<PQ>
<PQContact>
<userID>Test</userID>
<password>Test#2</password>
</PQContact>
<workflowStatusComment>
<comment>Issue released. Routing Status changed from CATCHALL to Pharmancy. Issue updated by user DT76747.</comment>
</workflowStatusComment>
</PQ>
</whiteboard>
<requestNodeName>//PQ</requestNodeName>
<responseNodeName>//PQ</responseNodeName>
<jobDB>
<name>PQCustomerService</name>
<userID>sa</userID>
<password>password</password>
</jobDB>
</performJob>
</SOAP:Body>
<response>
<DST xml:lang="en-US">
<jobName version="1.0">SRVChangeLock</jobName>
<trace>0</trace>
<readable>N</readable>
<AWD>
<userID>DT76747</userID>
<password>Removed for security purposes</password>
<transaction id="2016-07-07-02.02.19.127220T01">
<createTime time="Y">2016-07-07T02:02:19:127220-05:00</createTime>
<assignedTo>DT76747</assignedTo>
<lockedBy>DT76747</lockedBy>
<customScreen>WRKXMPL</customScreen>
<workflow route="Status">
<workStep status="_NEXT" next="Y" />
</workflow>
</transaction>
</AWD>
<jobVersion>1.0</jobVersion>
<jobReturn jobName="SRV00017">
<taskName />
<description />
<value>0</value>
</jobReturn>
</DST>
</response>
</SOAP:Envelope>
</PQ>
</whiteboard>
</response:performJobResponse>
</SOAP:Body>
<response>
<DST xml:lang="en-US">
<jobName version="1.0">SRVObjectUpdate</jobName>
<trace>0</trace>
<readable>N</readable>
<AWD>
<userID>DT76747</userID>
<password>Removed for security purposes</password>
<transaction id="2016-07-07-02.02.19.127220T01" workSelected="false" hasChildWork="N" children="N" hasParent="Y" hasParentCase="Y" hasChildSource="N">
<id>2016-07-07-02.02.19.127220T01</id>
</transaction>
</AWD>
</DST>
</response>
</SOAP:Envelope>
</PQ>
</whiteboard>
<jobReturn>
<value>0</value>
</jobReturn>
</response:performJobResponse>
</SOAP:Body>
</SOAP:Envelope>
I want to remove all the xmlns content,SOAP:Envelope, <SOAP:Body> and <response>tag related content.
My final xml should be as below:
<?xml version="1.0" encoding="UTF-8"?>
<PQ>
<PQContact>
<userID>Test</userID>
<password>Test#2</password>
</PQContact>
<workflowStatusComment>
<comment>Issue released. Routing Status changed from CATCHALL to Pharmancy. Issue updated by user DT76747.</comment>
</workflowStatusComment>
</PQ>
Could you please help me out?
Please, try this transformation:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:response="http://tempuri.org/">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="//SOAP:Body/performJob//whiteboard/node()"/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>

XSLT - multiple elements values are coming in single read

I am trying to read the number element value using below xsl.
XML:
<message channel-id="64E523E5-7A27-4343-A62A-AA8FBD24EB59">
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<insertResponse>
<sys_id>4342e2a24fb142005b0e4fe18110c7f3</sys_id>
<number>INC0010038</number>
</insertResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</message>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<message>
<send-parameters>
<agent-parameter>
<name>IncidentNumber</name>
<value><xsl:value-of select="message/s:Envelope/s:Body/t:insertResponse/t:number" /></value>
</agent-parameter>
</send-parameters>
</message>
</xsl:template>
</xsl:stylesheet>
The output i am getting is as below.
<?xml version="1.0" encoding="UTF-8"?>
<message>
<send-parameters>
<agent-parameter>
<name>IncidentNumber</name>
<value>4342e2a24fb142005b0e4fe18110c7f3
INC0010038</value>
</agent-parameter>
</send-parameters>
</message>
The value element is getting value from both sys-id and number tags 4342e2a24fb142005b0e4fe18110c7f3INC0010038. I want to read only number tag from the xml. I am sure that i am missing something very basic here. Please help me with that.
Regards,
Kiran
Try out the following:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
exclude-result-prefixes="env xsl">
<xsl:template match="/">
<message>
<send-parameters>
<agent-parameter>
<name>IncidentNumber</name>
<value>
<xsl:value-of select="message/env:Envelope/env:Body/insertResponse/number" />
</value>
</agent-parameter>
</send-parameters>
</message>
</xsl:template>
</xsl:stylesheet>
As stated by Micheal you are missing namespace definition in your stylesheet. Once you do that your code is good to go

xsl template match ignore namespace

I've read a lot of examples about ignore namespaces but can't seem to bring this concept to fruition inside template match.
Here's my sample xml:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<Response xmlns:ResB="http://www.aaa.com/v1" xmlns:dpconf="http://www.datapower.com/param/config" xmlns:exsl="http://xmlns.opentechnology.org/xslt-extensions/common" xmlns="http://www.aaa.com/v2">
<Status>
<Code>00000</Code>
</Status>
</Response>
</soapenv:Body>
</soapenv:Envelope>
And I can't have the namespace in the ouptut. Here's an example of the desired output:
<A>
<Transformed>0000</Transformed>
</A>
This isn't outputting my nodes, so how can I have an xslt to match the Response node and work off of that?
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//*[local-name() = 'Response']">
<A>
<Transformed><xsl:value-of select="Status/Code"/></Transformed>
</A>
Why would you want to ignore the namespace? Just declare it and use it.
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:v2="http://www.aaa.com/v2"
exclude-result-prefixes="v2"
>
<xsl:template match="v2:Response">
<A>
<Transformed>
<xsl:value-of select="v2:Status/v2:Code" />
</Transformed>
</A>
</xsl:template>
</xsl:stylesheet>

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>