XML to XML transformation is usually very simple with XSLT. There are two main roads to follow:
1. If you only need to cherry-pick a couple of values, use the Pull Approach.
2. If you need most of the original data, but reformat some of them (e.g., different wrapper, convert certain attributes to elements, etc.), use the Push Approach.
Here's a basic example of each method:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- Basic *Pull Approach* example: -->
<xsl:template match="/">
<!-- Create a wrapper and count all ItemDetails in file -->
<extract totalCount="{count(//ItemDetails)}">
<!-- Grab a single (but entire) record and copy to output -->
<xsl:copy-of select="//ItemDetails[ItemNumber = 123456]" />
</extract>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- Basic *Push Approach* example: -->
<!-- Identity transform -->
<xsl:template match="* | text()">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="* | text()" />
</xsl:copy>
</xsl:template>
<!-- Special template to correct all <ItemWidth> elements: -->
<xsl:template match="ItemWidth">
<xsl:copy>
<xsl:value-of select=". * 10" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
So, maybe you should try posting an example of the actual input XML you have, and the desired output XML you need?
Here is a sample of my xml. This just shows 1 itemdetail for each job. However, each job can have more than 1 itemdetail.
<?xml version="1.0" encoding="ISO-8859-1" ?> <JobFile> <JobDetails> <JobNumber>90903</JobNumber> <ItemDetails> <ItemNumber>10</ItemNumber> <ItemSorCode>CY00478</ItemSorCode> <ItemSorName>Provide necessary resources to site, in order to carry out welding and metal work repairs to fire barriers.</ItemSorName> <ItemQuantity>1.00</ItemQuantity> <ItemWidth>0</ItemWidth> <ItemLength>0</ItemLength> <ItemDepth>0</ItemDepth> </ItemDetails> </JobDetails> </JobFile>
Sorry that's the output I require. Here is the source xml
<?xml version="1.0" encoding="iso-8859-1" ?> - <Report Name="Conway 0650 Job items"> - <table1> - <table1_JobNumber_Collection> - <table1_JobNumber JobNumber="3401"> - <Detail_Collection> <Detail ItemNumber="10" ItemSorCode="H0101" ItemSorName="Take up 305mm x 200mm granite kerb, re-square ends as necessary and stack for re-use. Break out 150mm thick concrete foundation and concrete haunch. Load and cart waste to tip." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" /> <Detail ItemNumber="10" ItemSorCode="H0101" ItemSorName="Take up 305mm x 200mm granite kerb, re-square ends as necessary and stack for re-use. Break out 150mm thick concrete foundation and concrete haunch. Load and cart waste to tip." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" /> <Detail ItemNumber="10" ItemSorCode="H0101" ItemSorName="Take up 305mm x 200mm granite kerb, re-square ends as necessary and stack for re-use. Break out 150mm thick concrete foundation and concrete haunch. Load and cart waste to tip." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" /> <Detail ItemNumber="20" ItemSorCode="H0104" ItemSorName="Lay 305mm x 200mm granite kerb to Clause 1109.1AR with 150mm thick, grade C7.5P (ST1) concrete foundation and grade C7.5P (ST1) concrete haunch. Include laying to radius, angled or dropped kerbs with flush or 20mm kerb face." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" /> <Detail ItemNumber="20" ItemSorCode="H0104" ItemSorName="Lay 305mm x 200mm granite kerb to Clause 1109.1AR with 150mm thick, grade C7.5P (ST1) concrete foundation and grade C7.5P (ST1) concrete haunch. Include laying to radius, angled or dropped kerbs with flush or 20mm kerb face." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" /> <Detail ItemNumber="20" ItemSorCode="H0104" ItemSorName="Lay 305mm x 200mm granite kerb to Clause 1109.1AR with 150mm thick, grade C7.5P (ST1) concrete foundation and grade C7.5P (ST1) concrete haunch. Include laying to radius, angled or dropped kerbs with flush or 20mm kerb face." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" /> </Detail_Collection> </table1_JobNumber>
I need an ItemDetails tag before each <ItemNumber> and after each closing <ItemDepth> tag
also a <Job Details> tag after each <ItemDeatils> for each Job
Like this:
- <JobDetails> <JobNumber>10411141</JobNumber> - <ItemDetails> <ItemNumber>10</ItemNumber> <ItemSorCode>CY02601</ItemSorCode> <ItemSorName>Collect litter bin from depot and deliver to site.</ItemSorName> <ItemQuantity>1.00</ItemQuantity> <ItemWidth>0</ItemWidth> <ItemLength>0</ItemLength> <ItemDepth>0</ItemDepth> </ItemDetails> - <ItemDetails> <ItemNumber>20</ItemNumber> <ItemSorCode>CY02606</ItemSorCode> <ItemSorName>Break out and cart litter bin to tip or depot, including removal of 4 no bolts in any footway material and reinstate with mortar.</ItemSorName> <ItemQuantity>1.00</ItemQuantity> <ItemWidth>0</ItemWidth> <ItemLength>0</ItemLength> <ItemDepth>0</ItemDepth> </ItemDetails> - <ItemDetails> <ItemNumber>30</ItemNumber> <ItemSorCode>CY02605</ItemSorCode> <ItemSorName>Fix litter bin in any footway material including take up existing material, cutting and reinstatement</ItemSorName> <ItemQuantity>1.00</ItemQuantity> <ItemWidth>0</ItemWidth> <ItemLength>0</ItemLength> <ItemDepth>0</ItemDepth> </ItemDetails> </JobDetails>
xml to xml using xslt
Hi there,
I am new to this group and to xml. I have to format an output file to xml using xlst.
I have the following structure for the xml which is dervied from MS REporting Services:
Job Details - Header
Job Number - Always 1 Job Number can have 1 or more ItemDetails
ItemDetails - 1 or more for each Job Number
ItemNumber
ItemSorCode
ItemSorName
Job_Item_Quantity
ItemWidth
ItemLength
ItemDepth
ItemDetails
Job Details
Can someone please help with the transformation. Any help, pointers much appreciated.
Hi pisces113 (great name, btw :-)
XML to XML transformation is usually very simple with XSLT. There are two main roads to follow:
1. If you only need to cherry-pick a couple of values, use the Pull Approach.
2. If you need most of the original data, but reformat some of them (e.g., different wrapper, convert certain attributes to elements, etc.), use the Push Approach.
Here's a basic example of each method:
So, maybe you should try posting an example of the actual input XML you have, and the desired output XML you need?
/Chriztian
Thanks Chriztian,
Here is a sample of my xml. This just shows 1 itemdetail for each job. However, each job can have more than 1 itemdetail.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<JobFile>
<JobDetails>
<JobNumber>90903</JobNumber>
<ItemDetails>
<ItemNumber>10</ItemNumber>
<ItemSorCode>CY00478</ItemSorCode>
<ItemSorName>Provide necessary resources to site, in order to carry out welding and metal work repairs to fire barriers.</ItemSorName>
<ItemQuantity>1.00</ItemQuantity>
<ItemWidth>0</ItemWidth>
<ItemLength>0</ItemLength>
<ItemDepth>0</ItemDepth>
</ItemDetails>
</JobDetails>
</JobFile>
TIA
- and what should the above be transformed into? What do you expect as output?
/Chriztian
Sorry that's the output I require. Here is the source xml
<?xml version="1.0" encoding="iso-8859-1" ?>
- <Report Name="Conway 0650 Job items">
- <table1>
- <table1_JobNumber_Collection>
- <table1_JobNumber JobNumber="3401">
- <Detail_Collection>
<Detail ItemNumber="10" ItemSorCode="H0101" ItemSorName="Take up 305mm x 200mm granite kerb, re-square ends as necessary and stack for re-use. Break out 150mm thick concrete foundation and concrete haunch. Load and cart waste to tip." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" />
<Detail ItemNumber="10" ItemSorCode="H0101" ItemSorName="Take up 305mm x 200mm granite kerb, re-square ends as necessary and stack for re-use. Break out 150mm thick concrete foundation and concrete haunch. Load and cart waste to tip." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" />
<Detail ItemNumber="10" ItemSorCode="H0101" ItemSorName="Take up 305mm x 200mm granite kerb, re-square ends as necessary and stack for re-use. Break out 150mm thick concrete foundation and concrete haunch. Load and cart waste to tip." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" />
<Detail ItemNumber="20" ItemSorCode="H0104" ItemSorName="Lay 305mm x 200mm granite kerb to Clause 1109.1AR with 150mm thick, grade C7.5P (ST1) concrete foundation and grade C7.5P (ST1) concrete haunch. Include laying to radius, angled or dropped kerbs with flush or 20mm kerb face." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" />
<Detail ItemNumber="20" ItemSorCode="H0104" ItemSorName="Lay 305mm x 200mm granite kerb to Clause 1109.1AR with 150mm thick, grade C7.5P (ST1) concrete foundation and grade C7.5P (ST1) concrete haunch. Include laying to radius, angled or dropped kerbs with flush or 20mm kerb face." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" />
<Detail ItemNumber="20" ItemSorCode="H0104" ItemSorName="Lay 305mm x 200mm granite kerb to Clause 1109.1AR with 150mm thick, grade C7.5P (ST1) concrete foundation and grade C7.5P (ST1) concrete haunch. Include laying to radius, angled or dropped kerbs with flush or 20mm kerb face." job_item_quantity="2.00" ItemWidth="0.00" ItemLEngth="2.00" ItemDepth="0.00" />
</Detail_Collection>
</table1_JobNumber>
this is repeated....
input Transformed Output
<table1_JobNumber JobNumber> = <JobNumber>
<Detail_Collection> = <ItemDetails>
<Detail
ItemNumber = ItemNumber
ItemSorCode = ItemSorCode
ItemSorName = ItemSorName
job_item_quantity = ItemQuantity
ItemWidth = ItemWidth
ItemLEngth = ItemLength
ItemDepth = ItemDepth >
Hi again,
See what you can do with these templates:
How are you performing the actual transform - through Umbraco or something completely different?
/Chriztian
Your XML file seems to be wrong. You can only have one root element.
1 or more for each Job Number
ItemNumber
ItemSorCode
ItemSorName
Job_Item_Quantity
ItemWidth
ItemLength
ItemDepth
ItemDetails
thanks Chriztian
Thanks for your help Chriztian!! I applied the stylesheet and the output looks MUCH better than what I had. There is one small issue.
There can be many <itemDetails> within a <JobNumber> and the <JobNumber> is not being shown. It's only showing for the FIRST <JobNumber>
So, wt the moment, only the FIRST <JobNumber> is given and <ItemDetails> closes after that <JobNumber>
<ItemDetails> then begins again for the new <JobNumber> even though the JobNumber is not shown.
So I have this
<Job Details>
<JobNumber> </JobNumber>
<ItemDetails>
<itemNumber> </ItemNumber> --1st Item for this <JobNumber>
<itemSorCode> </ItemSorCode>
<itemSorName> </ItemSorName>
<JobItemQuantity> </JobItemQuantity>
<itemWidth> </ItemWidth>
<itemLength> </ItemLength>
<itemDepth> </ItemDepth>
<itemNumber> </ItemNumber> --2nd item for this <JobNumber>
<itemSorCode> </ItemSorCode>
<itemSorName> </ItemSorName>
<JobItemQuantity> </JobItemQuantity>
<itemWidth> </ItemWidth>
<itemLength> </ItemLength>
<itemDepth> </ItemDepth>
<itemNumber> </ItemNumber> --3rd item for this <JobNumber>
<itemSorCode> </ItemSorCode>
<itemSorName> </ItemSorName>
<JobItemQuantity> </JobItemQuantity>
<itemWidth> </ItemWidth>
<itemLength> </ItemLength>
<itemDepth> </ItemDepth>
<itemNumber> </ItemNumber> -- 4th item for this <JobNumber>
<itemSorCode> </ItemSorCode>
<itemSorName> </ItemSorName>
<JobItemQuantity> </JobItemQuantity>
<itemWidth> </ItemWidth>
<itemLength> </ItemLength>
<itemDepth> </ItemDepth>
</ItemDetails> -- This close for the current <JobNumber>
<ItemDetails> -- Start of a new <JobNumber>
But the <JobNumber> node is missing here.
The xml follows like this (after <ItemDetails>:
<itemNumber> </ItemNumber>
<itemSorCode> </ItemSorCode>
<itemSorName> </ItemSorName>
<JobItemQuantity> </JobItemQuantity>
<itemWidth> </ItemWidth>
<itemLength> </ItemLength>
<itemDepth> </ItemDepth>
TIA
Yeah, that makes total sense the way he coded it (me, that is :-)
You need to change the table1_JobNumber_Collection template and add another for table1_JobNumber, like this:
/Chriztian
Will give that a go. Thanks for your help Chriztian!!
Hi Chriztian,
It needs a bit of tweaking:
I need an ItemDetails tag before each <ItemNumber> and after each closing <ItemDepth> tag
also a <Job Details> tag after each <ItemDeatils> for each Job
Like this:
- <JobDetails>
<JobNumber>10411141</JobNumber>
- <ItemDetails>
<ItemNumber>10</ItemNumber>
<ItemSorCode>CY02601</ItemSorCode>
<ItemSorName>Collect litter bin from depot and deliver to site.</ItemSorName>
<ItemQuantity>1.00</ItemQuantity>
<ItemWidth>0</ItemWidth>
<ItemLength>0</ItemLength>
<ItemDepth>0</ItemDepth>
</ItemDetails>
- <ItemDetails>
<ItemNumber>20</ItemNumber>
<ItemSorCode>CY02606</ItemSorCode>
<ItemSorName>Break out and cart litter bin to tip or depot, including removal of 4 no bolts in any footway material and reinstate with mortar.</ItemSorName>
<ItemQuantity>1.00</ItemQuantity>
<ItemWidth>0</ItemWidth>
<ItemLength>0</ItemLength>
<ItemDepth>0</ItemDepth>
</ItemDetails>
- <ItemDetails>
<ItemNumber>30</ItemNumber>
<ItemSorCode>CY02605</ItemSorCode>
<ItemSorName>Fix litter bin in any footway material including take up existing material, cutting and reinstatement</ItemSorName>
<ItemQuantity>1.00</ItemQuantity>
<ItemWidth>0</ItemWidth>
<ItemLength>0</ItemLength>
<ItemDepth>0</ItemDepth>
</ItemDetails>
</JobDetails>
Here is my xslt in its entirety:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008"
xmlns:rdl="http://schemas.microsoft.com/sqlserver/reporting/2008">
<xsl:template match="table1_JobNumber_Collection">
<JobFile>
<JobDetails>
<xsl:apply-templates select="table1_JobNumber" />
</JobDetails>
</JobFile>
</xsl:template>
<xsl:template match="Detail_Collection">
<ItemDetails>
<xsl:apply-templates />
</ItemDetails>
</xsl:template>
<xsl:template match = "Detail">
<xsl:apply-templates select = "@*"/>
</xsl:template>
<xsl:template match = "Detail/@*">
<xsl:element name="{name()}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
<xsl:template match="table1_JobNumber">
<JobNumber>
<xsl:value-of select="@JobNumber"/>
</JobNumber>
<xsl:apply-templates select="Detail_Collection" />
</xsl:template>
<xsl:template match="Detail/@ItemNumber">
<ItemNumber>
<xsl:value-of select ="."/>
</ItemNumber>
</xsl:template>
<xsl:template match="Detail/@ItemSorCode">
<ItemSorCode>
<xsl:value-of select ="."/>
</ItemSorCode>
</xsl:template>
<xsl:template match="Detail/@ItemSorName">
<ItemSorName>
<xsl:value-of select ="."/>
</ItemSorName>
</xsl:template>
<xsl:template match="Detail/@job_item_quantity">
<JobItemQuantity>
<xsl:value-of select ="."/>
</JobItemQuantity>
</xsl:template>
<xsl:template match="Detail/@ItemWidth">
<ItemWidth>
<xsl:value-of select ="."/>
</ItemWidth>
</xsl:template>
<xsl:template match="Detail/@ItemLEngth">
<ItemLength>
<xsl:value-of select ="."/>
</ItemLength>
</xsl:template>
<xsl:template match="Detail/@ItemDepth">
<ItemDepth>
<xsl:value-of select ="."/>
</ItemDepth>
</xsl:template>
</xsl:stylesheet>
TIA
Can anybody help with the above? I'm still stuck
TIA
is working on a reply...