XSLT Multiple Child - xslt

I have an XML which has multiple child elements. Item Group will be only once and can have minimum or more Transactions for each Item_Entry. In other words, Item_Entry will have only one Item_Group, but can have one more more Transactions. I need to generate my output based on the transaction. My output should contain all the transactions for each item. I need some help with XSLT for this.
XML:
<?xml version='1.0' encoding='UTF-8'?>
<Item_Data>
<Item_Entry>
<Item_group>
<Item_Name>Name1</Item_Name>
<Item_ID>0001</Item_ID>
<Sale_Date>2019-01-01-00:00</Sale_Date>
</Item_group>
<Transaction>
<TxnCode Description="Store1">
<Store type="StoreNum">1001</Store>
</TxnCode>
<SalesTime>2019-01-01-07:00</SalesTime>
<SaleAmount>10</SaleAmount>
</Transaction>
<Transaction>
<TxnCode Description="Store2">
<Store type="StoreNum">1002</Store>
</TxnCode>
<SalesTime>2019-01-01-08:00</SalesTime>
<SaleAmount>11</SaleAmount>
</Transaction>
</Item_Entry>
<Item_Entry>
<Item_group>
<Item_Name>Name2</Item_Name>
<Item_ID>0002</Item_ID>
<Sale_Date>2019-01-02-00:00</Sale_Date>
</Item_group>
<Transaction>
<TxnCode Description="Store3">
<Store type="StoreNum">1003</Store>
</TxnCode>
<SalesTime>2019-01-02-09:00</SalesTime>
<SaleAmount>12</SaleAmount>
</Transaction>
<Transaction>
<TxnCode Description="Store4">
<Store type="StoreNum">1004</Store>
</TxnCode>
<SalesTime>2019-01-02-10:00</SalesTime>
<SaleAmount>13</SaleAmount>
</Transaction>
</Item_Entry>
</Item_Data>
Output:
Item_ID,Item_Name,Sale_Date,Store_Name,Store_Num,Sales_Time,Sale_Amount
0001,Name1,2019-01-01,Store1,1001,2019-01-01-07:00,10
0001,Name1,2019-01-01,Store2,1002,2019-01-01-08:00,11
0002,Name2,2019-01-02,Store3,1003,2019-01-01-09:00,12
0002,Name2,2019-01-02,Store4,1004,2019-01-01-10:00,13
Thanks,
Ug

For XML to CSV or one "record" per line transformation I think (at least in XSLT 2/3) it is easy to push the relevant element representing a "record" or line to a template (i.e. in your case <xsl:apply-templates select="//Transaction"/>) and then in there to collect all data you want to output in the select of an xsl:value-of with the right separator e.g.
<?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="#all"
version="3.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:text>Item_ID,Item_Name,Sale_Date,Store_Name,Store_Num,Sales_Time,Sale_Amount
</xsl:text>
<xsl:apply-templates select="//Transaction"/>
</xsl:template>
<xsl:template match="Transaction">
<xsl:value-of select="../Item_group!(Item_ID, Item_Name, substring(Sale_Date, 1, 10)), */#* | .//*[not(*)]" separator=","/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jz1PuNX

Related

XSLT: Convert JSON to XML, then transform, in one XSLT

I'm trying to convert JSON to a specific XML format, all in one XSLT. (It doesn't have to be in one step, but, you know,...)
I can convert the JSON to generic XML from here: How to use XPath/XSLT fn:json-to-xml
Converting the resultant generic XML to the XML I want is then simple.
But I can't work out how to combine the XSLTs so I can do it in one step, do JSON-to-XML and then the XML transformation. I've tried with variables, include, import, but can't get it to work.
I suspect it's straightforward! It needs to be in (just) XSLT.
So, from the question linked to above, I start with JSON (in XML tags)
<root>
<data>{
"desc" : "Distances between several cities, in kilometers.",
"updated" : "2014-02-04T18:50:45",
"uptodate": true,
"author" : null,
"cities" : {
"Brussels": [
{"to": "London", "distance": 322},
{"to": "Paris", "distance": 265},
{"to": "Amsterdam", "distance": 173}
],...
and transform to
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="desc">Distances between several cities, in kilometers.</string>
<string key="updated">2014-02-04T18:50:45</string>
<boolean key="uptodate">true</boolean>
<null key="author"/>
<map key="cities">
<array key="Brussels">
<map>
<string key="to">London</string>
<number key="distance">322</number>
</map>
<map>
<string key="to">Paris</string>
<number key="distance">265</number>
</map>...
using
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math" version="3.0">
<xsl:output indent="yes"/>
<xsl:template match="data">
<xsl:copy-of select="json-to-xml(.)"/>
</xsl:template>
</xsl:stylesheet>
Now I can apply this stylesheet to the 'intermediate' XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://www.w3.org/2005/xpath-functions">
<xsl:output indent="yes"/>
<xsl:template match="/">
<Distances>
<xsl:for-each select="f:map/f:map/f:array">
<Start>
<StartPoint><xsl:value-of select="#key"/></StartPoint>
<xsl:for-each select="f:map">
<Distance>
<xsl:attribute name="end"><xsl:value-of select="f:string"/></xsl:attribute>
<xsl:attribute name="value"><xsl:value-of select="f:number"/></xsl:attribute>
</Distance>
</xsl:for-each>
</Start>
</xsl:for-each>
</Distances>
</xsl:template>
</xsl:stylesheet>
and get my desired structure:
<?xml version="1.0" encoding="UTF-8"?>
<Distances xmlns:f="http://www.w3.org/2005/xpath-functions">
<Start>
<StartPoint>Brussels</StartPoint>
<Distance end="London" value="322"/>
<Distance end="Paris" value="265"/>
<Distance end="Amsterdam" value="173"/>
</Start>...
So, is it possible to combine the JSON-to-XML and the XML transformation XSLs in one?
I am guessing you want to do:
XSLT 3.0
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://www.w3.org/2005/xpath-functions"
exclude-result-prefixes="f">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/root">
<Distances>
<xsl:for-each select="json-to-xml(data)/f:map/f:map/f:array">
<Start>
<StartPoint>
<xsl:value-of select="#key"/>
</StartPoint>
<xsl:for-each select="f:map">
<Distance end="{f:string}" value="{f:number}"/>
</xsl:for-each>
</Start>
</xsl:for-each>
</Distances>
</xsl:template>
</xsl:stylesheet>
Untested, because no code suitable for testing was provided.
To do it the way you were proposing, you can do
<xsl:template match="data">
<xsl:apply-templates select="json-to-xml(.)"/>
</xsl:template>
and then add template rules to transform the generic XML produced by json-to-xml() to your application-specific XML.
But I think the approach suggested by #michael.hor257k is probably better.

Adding missing nodes to XML via XSLT

I'm using a tool to import XML files into Dynamics NAV, but some parties providing the XML files skip empty nodes. My tool (external) can not handle those situation so I want to include XSLT to add the missing nodes. The xslt works fine for 1 node, but adding multiple nodes does not work. So I must be doing something wrong.
I'm building an integration to Dynamics NAV to insert Sales Orders. The orders are delivered from multiple parties using a XML file. However some of the parties providing the XML do not list all nodes in their XML file, they skip the empty ones. I'm using a tool build within Dynamics NAV (Add-on from other vendor) to import those files. However some XML files go wrong because of the fact that some (empty) nodes are missing in the XML file. I know this is an issue within the add-on but I need a solution on short notice. So created an XSLT to add the missing nodes. It works fine with 1 missing node, but it is not able to add both missing nodes. I'm not that familiar with XSLT so most of the times it is trial & error. Perhaps someone can help me with this.
This is the XML file format that is provided, The nodes that are sometimes missing is the DeliveryParty node and the DeliveryAddress part.
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<Orders>
<Order>
<Partner>
<SenderEANCode>9999999999999</SenderEANCode>
<RecipientEANCode>9999999999999</RecipientEANCode>
</Partner>
<OrderHeader>
<OrderVersion>008</OrderVersion>
<OrderTypeCode>220</OrderTypeCode>
<Document>
<DocumentNumber>34034040</DocumentNumber>
<Date>2019-04-18</Date>
</Document>
<DeliveryDate>2019-04-24</DeliveryDate>
<CompleteDelivery>YES</CompleteDelivery>
<Supplier>9999999999999</Supplier>
<Buyer>9999999999999</Buyer>
<Invoicee>9999999999999</Invoicee>
<DeliveryParty>9999999999999</DeliveryParty>
<DeliveryAddress>
<DeliveryName>Private Customer</DeliveryName>
<DeliveryStreet>Teststraat</DeliveryStreet>
<DeliveryCity>TestCity</DeliveryCity>
<DeliveryCountry>NL</DeliveryCountry>
<DeliveryTelNo></DeliveryTelNo>
<DeliveryEmail>test#test.com</DeliveryEmail>
</DeliveryAddress>
</OrderHeader>
<OrderLine>
<LineItemNumber>1</LineItemNumber>
<GTIN>9999999999999</GTIN>
<OrderedQuantity>
<Quantity>260</Quantity>
</OrderedQuantity>
</OrderLine>
</Order>
</Orders>
Sometimes the DeliveryParty node is missing and other times the DeliveryAddress part including subnodes is missing. I created the following XSLT to add those nodes but as it is trail and error I need some help to fix this. I'm a novice to XSLT, I can so some small changes but I do not use it frequently so knowledge is fading away quickly.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Orders/Order/OrderHeader[not(DeliveryParty)]">
<xsl:copy-of select="*"/>
<DeliveryParty/>
</xsl:template>
<xsl:template match="Orders/Order/OrderHeader[not(//DeliveryAddress)]">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
<DeliveryAddress>
<DeliveryName></DeliveryName>
<DeliveryStreet></DeliveryStreet>
<DeliveryPostalCode></DeliveryPostalCode>
<DeliveryCity></DeliveryCity>
<DeliveryCountry></DeliveryCountry>
<DeliveryTelNo></DeliveryTelNo>
<DeliveryEmail></DeliveryEmail>
</DeliveryAddress>
</xsl:copy>
</xsl:template>
With above mentioned XSLT the DeliveryAddress node with it's subnodes is added but the deliveryparty is not.
When the file is delivered like this:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<Orders>
<Order>
<Partner>
<SenderEANCode>9999999999999</SenderEANCode>
<RecipientEANCode>9999999999999</RecipientEANCode>
</Partner>
<OrderHeader>
<OrderVersion>008</OrderVersion>
<OrderTypeCode>220</OrderTypeCode>
<Document>
<DocumentNumber>34034040</DocumentNumber>
<Date>2019-04-18</Date>
</Document>
<DeliveryDate>2019-04-24</DeliveryDate>
<CompleteDelivery>YES</CompleteDelivery>
<Supplier>9999999999999</Supplier>
<Buyer>9999999999999</Buyer>
<Invoicee>9999999999999</Invoicee>
</OrderHeader>
<OrderLine>
<LineItemNumber>1</LineItemNumber>
<GTIN>9999999999999</GTIN>
<OrderedQuantity>
<Quantity>260</Quantity>
</OrderedQuantity>
</OrderLine>
</Order>
</Orders>
The outcome should be this:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<Orders>
<Order>
<Partner>
<SenderEANCode>9999999999999</SenderEANCode>
<RecipientEANCode>9999999999999</RecipientEANCode>
</Partner>
<OrderHeader>
<OrderVersion>008</OrderVersion>
<OrderTypeCode>220</OrderTypeCode>
<Document>
<DocumentNumber>34034040</DocumentNumber>
<Date>2019-04-18</Date>
</Document>
<DeliveryDate>2019-04-24</DeliveryDate>
<CompleteDelivery>YES</CompleteDelivery>
<Supplier>9999999999999</Supplier>
<Buyer>9999999999999</Buyer>
<Invoicee>9999999999999</Invoicee>
<DeliveryParty></DeliveryParty>
<DeliveryAddress>
<DeliveryName></DeliveryName>
<DeliveryStreet></DeliveryStreet>
<DeliveryCity></DeliveryCity>
<DeliveryCountry></DeliveryCountry>
<DeliveryTelNo></DeliveryTelNo>
<DeliveryEmail></DeliveryEmail>
</DeliveryAddress>
</OrderHeader>
<OrderLine>
<LineItemNumber>1</LineItemNumber>
<GTIN>9999999999999</GTIN>
<OrderedQuantity>
<Quantity>260</Quantity>
</OrderedQuantity>
</OrderLine>
</Order>
</Orders>
How about:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="OrderHeader">
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="not(DeliveryParty)">
<DeliveryParty/>
</xsl:if>
<xsl:if test="not(DeliveryAddress)">
<DeliveryAddress>
<DeliveryName/>
<DeliveryStreet/>
<DeliveryPostalCode/>
<DeliveryCity/>
<DeliveryCountry/>
<DeliveryTelNo/>
<DeliveryEmail/>
</DeliveryAddress>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Group XML using xslt based on Header or Document Entry

How to group the XML using xlst for the below xml code.
Following are the input XML: I'm using this input xml in order to import into an ERP system.
<row>
<Ref>1</Ref>
<Code>IT001</Code>
<Qty>11</Qty>
</row>
<row>
<Ref>1</Ref>
<Code>IT002</Code>
<Qty>21</Qty>
</row>
<row>
<Ref>2</Ref>
<Code>IT002</Code>
<Qty>12</Qty>
</row>
following are the Output or expected XML: ERP system generally accepts one line per document and it's siblings of document lines. Thus the following desired output is required.
<Document>
<Ref>1</Ref><Lines>
<Item>
<Code>IT001</Code>
<Qty>11</Qty>
</Item>
<Item>
<Code>IT002</Code>
<Qty>21</Qty>
</Item>
</Lines>
</Document>
<Document>
<OrderRef>2</OrderRef>
<Lines>
<Item>
<Code>IT002</Code>
<Qty>12</Qty>
</Item>
</Lines>
</Document>
Let's start from a correction of your source XML:
There must be only one root element (I called it Root)
and inside it there can be multiple (e.g. Document) elements.
The template performing the transformation should match the
Root element.
As I see from your expected output, you want to group Document
elements on DocumentRef, so in the script below there is
corresponding xsl:for-each-group instruction.
For each such group there should be Document output element
and inside it Ref element with the value of the current
grouping key.
Then there should be a Lines element and inside it, for each
member of the current group, there should be Item element
and inside it 2 child elements with required values from the
source element.
So the whole script can look like below:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="Root">
<xsl:copy>
<xsl:for-each-group select="Document" group-by="DocumentRef">
<Document>
<Ref><xsl:value-of select="current-grouping-key()"/></Ref>
<Lines>
<xsl:for-each select="current-group()">
<Item>
<ItemCode><xsl:value-of select="DocumentLines/ItemCode"/></ItemCode>
<Qty><xsl:value-of select="DocumentLines/ItemQty"/></Qty>
</Item>
</xsl:for-each>
</Lines>
</Document>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:transform>
For a working example, including corrected input, see http://xsltransform.net/eieE3PX
XSLT 1.0 version
In XSLT 1.0 it is also possible, using Muenchian Grouping:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="groups" match="row" use="OrderRef"/>
<xsl:template match="Payload">
<xsl:copy>
<xsl:apply-templates select="row[generate-id() = generate-id(
key('groups', OrderRef)[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="row">
<Document>
<Ref><xsl:value-of select="OrderRef"/></Ref>
<CardCode><xsl:value-of select="CustomerCode"/></CardCode>
<Lines>
<xsl:for-each select="key('groups', OrderRef)">
<Item>
<ItemCode><xsl:value-of select="ItemCode"/></ItemCode>
<Qty><xsl:value-of select="Quantity"/></Qty>
</Item>
</xsl:for-each>
</Lines>
</Document>
</xsl:template>
</xsl:transform>
The initial step is to create an xsl:key. Each key must have a name to
refer to it later. match defines which elements to include in this key
and use defines the grouping key.
Then look at:
<xsl:apply-templates select="row[generate-id() = generate-id(
key('groups', OrderRef)[1])]"/>
It "calls an action" (in this case xsl:apply-templates) on
the first object in each group.
The rest of code from my initial solution has been moved to
a template matching row.
The initial part of it performs actions for the current group
(generate output Document, Ref, CardCode and Lines
elements).
The rest (xsl:for-each) performs actions for individual
members of the current group, generating Item, ItemCode
and Qty elements.
I updated your solution in xsltransform, so you can view
it on http://xsltransform.net/jxWYjW2/2
Note that I changed the XSLT engine to Saxon 6.5.5. You can also
switch it to Xalan, although then you loose indentation.
If this approach is new to you, maybe you should read a little about
generate-id and Muenchian Grouping itself. Even StackOverflow contains
a lot of posts about these issues.

A sequence of more than one item is not allowed as the second argument of concat()

The below xsl works fine if I do not bring in the "other_location_postal_code" field, which is commented here.
This is because there are multiple records if I bring in that field.
How can I have this xsl evaluate each record so it would write this record twice, once for the one "other location postal code" and the other?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:e="http://www.taleo.com/ws/tee800/2009/01" xmlns:fct="http://www.taleo.com/xsl_functions" exclude-result-prefixes="e fct">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no"/>
<xsl:param name="OUTBOUND_FOLDER"/>
<xsl:template match="/">
<source>
<xsl:apply-templates select="//e:Requisition"/>
</source>
</xsl:template>
<xsl:template match="e:Requisition">
<xsl:variable name="job_id" select="e:ContestNumber"/>
<xsl:variable name="other_location_postal_code" select="e:JobInformation/e:JobInformation/e:OtherLocations/e:Location/e:NetworkLocation/e:NetworkLocation/e:ZipCode"/>
<job>
<job_id>
<xsl:value-of select="concat('<','![CDATA[',$job_id,']]','>')"/>
</job_id>
<other_location_postal_code>
<xsl:value-of select="concat('![CDATA[',$other_location_postal_code,']]')"/>
</other_location_postal_code>
</job>
</xsl:template>
</xsl:stylesheet>
I want it to come out like so:
<?xml version="1.0" encoding="UTF-8"?>
<source>
<job>
<job_id><![CDATA[15000005]]></job_id>
<other_location_postal_code><![CDATA[77382]]></other_location_postal_code>
</job>
<job>
<job_id><![CDATA[15000005]]></job_id>
<other_location_postal_code><![CDATA[37567]]></other_location_postal_code>
</job>
</source>
The initial XML looks like so:
<?xml version="1.0" encoding="UTF-8"?>
-<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>
-<ns1:getDocumentByKeyResponse xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
-<Document xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
-<Attributes>
<Attribute name="count">1</Attribute>
<Attribute name="duration">0:00:00.088</Attribute>
<Attribute name="entity">Requisition</Attribute>
<Attribute name="mode">T-XML</Attribute>
<Attribute name="version">http://www.taleo.com/ws/tee800/2009/01</Attribute>
</Attributes>
-<Content>
-<ExportTXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07" xmlns:e="http://www.taleo.com/ws/tee800/2009/01">
-<e:Requisition>
<e:ContestNumber>15000005</e:ContestNumber>
-<e:JobInformation>
-<e:JobInformation>
-<e:OtherLocations>
-<e:Location>
<e:ZipCode>77002</e:ZipCode>
</e:Location>
-<e:Location>
<e:ZipCode>77050</e:ZipCode>
</e:Location>
</e:OtherLocations>
</e:JobInformation>
</e:JobInformation>
</e:Requisition>
</ExportTXML>
</Content>
</Document>
</ns1:getDocumentByKeyResponse>
</soapenv:Body>
</soapenv:Envelope>
The error message simply says that an argument to the concat function is a sequence of more than one node. So some of your variable selects two or more nodes and concat expects as single node for each of its arguments. You will need to decide what you want to output, either only the first node with $var[1] or the concatenation with string-join($var, ' ').
Note that you don't need all those attempts to output CDATA section, you can tell the XSLT processor the cdata-section-elements on the xsl:output direction.
As you have now posted more details here is one suggestion to map each ZipCode element to job element:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:e="http://www.taleo.com/ws/tee800/2009/01"
exclude-result-prefixes="e">
<xsl:output indent="yes" cdata-section-elements="job_id other_location_postal_code"/>
<xsl:template match="/">
<source>
<xsl:apply-templates select="//e:OtherLocations/e:Location/e:ZipCode"/>
</source>
</xsl:template>
<xsl:template match="e:ZipCode">
<xsl:apply-templates select="ancestor::e:Requisition">
<xsl:with-param name="zc" select="current()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="e:Requisition">
<xsl:param name="zc"/>
<job>
<job_id><xsl:value-of select="e:ContestNumber"/></job_id>
<other_location_postal_code><xsl:value-of select="$zc"/></other_location_postal_code>
</job>
</xsl:template>
</xsl:stylesheet>

Combining input XML to produce another XML output

Trying to build a POC that does the following:
Given a short input XML, take the values from it and insert them into a larger XML file of a known format.
So if this was my input XML:
<root>
<transaction ID="TX123" source-system="xyz" timestamp="2015-10-15T14:20:35.954Z" dest-system="abc" status="success" applicationID="some_app" originator="MQ">
</transaction>
</root>
And i'd have to take these values and insert them into this: MQ FTE Transfer Log message format
I'd have to insert the values in the transferSet node (timestamp) and metaDataSet.
What would the XSLT have to look like in order to get this done?
Thanks a bunch in advance!
Slava.
Your XLS should look like this:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<transaction>
<!-- more elements... -->
<xsl:apply-templates select="transaction"/>
</transaction>
</xsl:template>
<xsl:template match="transaction">
<transferSet>
<xsl:attribute name="startTime"><xsl:value-of select="#timestamp" /></xsl:attribute>
<metaDataSet>
<metaData key="com.ibm.wmqfte.SourceAgent"><xsl:value-of select="#source-system"/></metaData>
<!-- more elements... -->
</metaDataSet>
</transferSet>
</xsl:template>
With your source input, it should generate an XML like this:
<?xml version="1.0" encoding="UTF-8"?>
<transaction>
<transferSet startTime="2015-10-15T14:20:35.954Z">
<metaDataSet>
<metaData key="com.ibm.wmqfte.SourceAgent">xyz</metaData>
</metaDataSet>
</transferSet>
</transaction>