Developer forum

Forum » Integration » XSLT transformation of XML

XSLT transformation of XML

Filip Lundby
Reply

In the Data integration module I'm creating an XSLT that transforms an XML into a new XML. This is my XSLT - just to see what is outputtet:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">

    <xsl:copy-of select="." />

  </xsl:template>

</xsl:stylesheet>

But when this is executed it tells me: "Error occured: Root element is missing."

Would appreciate if some one would show me a small working XSLT just to get me started.

 


Replies

 
Filip Lundby
Reply

Here's the rest of the log. Perhaps the error occurs while reading the config..?

11/29/2012 9:58:00 AM: Starting batch
11/29/2012 9:58:02 AM: Starting job - Mydata.
11/29/2012 9:58:11 AM: reading configuration
11/29/2012 9:58:11 AM: Error occured: Root element is missing.
11/29/2012 9:58:11 AM: Finished job - Mydata.
11/29/2012 9:58:11 AM: batch failed.

 

 
Dmitriy Benyuk
Reply

Hi Filip,
Could you send/attach the xml file which is causing this error? This will help us to reproduce this issue.
And what version of Dynamicweb you are using?
 

Best regards, Dmitrij

 
Filip Lundby
Reply

 

Hi Dmitriy

This is DW version 8.1.2.8


I've got two tasks.

1) The first task exports products to an XML - this works and looks like (not formatted in exported file):

<?xml version="1.0" encoding="utf-8"?>
<tables>
<table tableName="EcomProducts">
<item table="EcomProducts">
<column columnName="ProductID"><![CDATA[01-1]]></column>
<column columnName="ProductLanguageID"><![CDATA[LANG1]]></column>
<column columnName="ProductVariantID"><![CDATA[]]></column>
<column columnName="ProductDefaultShopID"><![CDATA[]]></column>
<column columnName="ProductNumber"><![CDATA[01-1]]></column>
<column columnName="ProductName"><![CDATA[Produkt1]]></column>
<column columnName="ProductShortDescription"><![CDATA[]]></column>
<column columnName="ProductLongDescription"><![CDATA[]]></column>
<column columnName="ProductLink1"><![CDATA[]]></column>
<column columnName="ProductLink2"><![CDATA[]]></column>
<column columnName="ProductPrice"><![CDATA[100.25]]></column>
<column columnName="ProductStock"><![CDATA[0]]></column>
<column columnName="ProductStockGroupID"><![CDATA[]]></column>
<column columnName="ProductVatGrpID"><![CDATA[]]></column>
<column columnName="ProductManufacturerID"><![CDATA[]]></column>
<column columnName="ProductType"><![CDATA[0]]></column>
<column columnName="ProductPriceType"><![CDATA[0]]></column>
<column columnName="ProductPriceCounter"><![CDATA[0]]></column>
<column columnName="ProductVariantCounter"><![CDATA[0]]></column>
<column columnName="ProductVariantProdCounter"><![CDATA[0]]></column>
<column columnName="ProductVariantGroupCounter"><![CDATA[0]]></column>
<column columnName="ProductUnitCounter"><![CDATA[0]]></column>
<column columnName="ProductDefaultUnitID"><![CDATA[]]></column>
<column columnName="ProductDefaultVariantComboID"><![CDATA[]]></column>
<column columnName="ProductPriceMatrixUnit"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixVariant"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixPeriod"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixMultiplePrices"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixQuantitySpecification"><![CDATA[]]></column>
<column columnName="producent" isNull="true"/>
<column columnName="ProductOptimizedFor"><![CDATA[]]></column>
<column columnName="ProductCategoryFieldValues"><![CDATA[<?xml version="1.0" encoding="utf-8" standalone="yes"?><Categories/>]]></column>
<column columnName="Groups"><![CDATA["Gruppe1"]]></column>
<column columnName="VariantGroups" isNull="true"/>
<column columnName="VariantOptions" isNull="true"/>
</item>
<item table="EcomProducts">
<column columnName="ProductID"><![CDATA[01-2]]></column>
<column columnName="ProductLanguageID"><![CDATA[LANG1]]></column>
<column columnName="ProductVariantID"><![CDATA[]]></column>
<column columnName="ProductDefaultShopID" isNull="true"/>
<column columnName="ProductNumber"><![CDATA[01-2]]></column>
<column columnName="ProductName"><![CDATA[Produkt2]]></column>
<column columnName="ProductShortDescription" isNull="true"/>
<column columnName="ProductLongDescription" isNull="true"/>
<column columnName="ProductLink1" isNull="true"/>
<column columnName="ProductLink2" isNull="true"/>
<column columnName="ProductPrice"><![CDATA[200]]></column>
<column columnName="ProductStock"><![CDATA[0]]></column>
<column columnName="ProductStockGroupID" isNull="true"/>
<column columnName="ProductVatGrpID" isNull="true"/>
<column columnName="ProductManufacturerID" isNull="true"/>
<column columnName="ProductType"><![CDATA[0]]></column>
<column columnName="ProductPriceType"><![CDATA[0]]></column>
<column columnName="ProductPriceCounter"><![CDATA[0]]></column>
<column columnName="ProductVariantCounter"><![CDATA[0]]></column>
<column columnName="ProductVariantProdCounter"><![CDATA[0]]></column>
<column columnName="ProductVariantGroupCounter"><![CDATA[0]]></column>
<column columnName="ProductUnitCounter"><![CDATA[0]]></column>
<column columnName="ProductDefaultUnitID" isNull="true"/>
<column columnName="ProductDefaultVariantComboID" isNull="true"/>
<column columnName="ProductPriceMatrixUnit"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixVariant"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixPeriod"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixMultiplePrices"><![CDATA[0]]></column>
<column columnName="ProductPriceMatrixQuantitySpecification" isNull="true"/>
<column columnName="producent" isNull="true"/>
<column columnName="ProductOptimizedFor" isNull="true"/>
<column columnName="ProductCategoryFieldValues" isNull="true"/>
<column columnName="Groups"><![CDATA["Gruppe1"]]></column>
<column columnName="VariantGroups" isNull="true"/>
<column columnName="VariantOptions" isNull="true"/>
</item>
</table>
</tables>​

 


2) The second task should transform the XML into a new custom XML using XSLT. Log returns:

11/29/2012 9:58:00 AM: Starting batch
11/29/2012 9:58:02 AM: Starting job - Mydata.
11/29/2012 9:58:11 AM: reading configuration
11/29/2012 9:58:11 AM: Error occured: Root element is missing.
11/29/2012 9:58:11 AM: Finished job - Mydata.
11/29/2012 9:58:11 AM: batch failed.
 

 

 

 
Dmitriy Benyuk
Reply

Hi Filip,
I have problem of saving the content of your xml file provided in your previous post to the new xml file.

Could you please attach the original xml file via Attachments -> Select file option ?
 

 
Filip Lundby
Reply
Sorry about that. Here it is attached :)
 
Dmitriy Benyuk
Reply

Hi Filip,
I have found the problem, it was connected with CDATA wrapping and it is now fixed in the new version of Dynamicweb 8.2.


However it is possible to use the following xslt file below for copying the xml content which wraps the "column" tag content into CDATA
(the fix was: cdata-section-elements="column"):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
 
  <xsl:output method="xml" indent="yes" cdata-section-elements="column"/>
 
  <xsl:template match="/">
 
    <xsl:copy-of select="." />
 
  </xsl:template>
 
</xsl:stylesheet>

 
Filip Lundby
Reply

Hi Dmitriy

This is not working for me. Right now we are forced to DW 8.1

I've been investigating further and found that af create a completely new transform-task I get this log message

12/3/2012 5:02:59 PM: Starting batch
12/3/2012 5:03:00 PM: Starting job - Transform.
12/3/2012 5:03:00 PM: reading configuration
12/3/2012 5:03:00 PM: Job run failed. No active mappings.
12/3/2012 5:03:00 PM: Finished job - Transform.
12/3/2012 5:03:00 PM: batch failed.

Then I edited the XSLT added: <xsl:value-of select="@tableName" />

And then it's back to "Root element is missing". Changing back the XSLT doesnt help.

Then again if I create a new task the log returns: "Job run failed. No active mappings."

 

 
Dmitriy Benyuk
Reply

Hi Filip,

have you put cdata-section-elements="column" in your xslt file?

"No active mappings" means that there is no mapping in your job seettings, check if you have any of them as it is shown in the attached screenshot.
If you will have the errors again, please attach: the source xml file with data and xslt file too.

mapping.jpg
 
Filip Lundby
Reply

Hi Dmitriy

Yes I added cdata-section-elements="column" to the XSLT. See attached XSLT and source-XML.

I see your point about mappings - but shouldn't the mappings be done by the XSLT?

To add mappings I deleted the tranformation task to create a new one. But now I cannot create the task:
http://screencast.com/t/3PodBvzeu

I'm not testing on the live-server, so for fun I upgraded to 8.2 but got the same error as in the video. Donwgraded to 8.1 again.

 

 
Dmitriy Benyuk
Reply

Hi Filip,
I have checked your attached xslt file and it was different from the correct one which I have posted here. The difference is that you have changed: <xsl:copy-of select="." /> to <xsl:value-of select="." /> - those are different xslt commands.
So, I have attached the correct xslt which was working for me on DW 8.1

 

Regarding the mapping: the mapping can't be done via XSLT, the mapping between source column to destination column is set in case if the source and destination column names are matching(they are the same), and it should be verified at creating the job(activity), because there can be a situations when those doesn't match.

 

For xslt testing you can use the online xslt tester app like that: http://xslttest.appspot.com/
 

 
Filip Lundby
Reply

Hi Dmitriy

Ok, seems to work now after adding mappings.

So I cannot edit the XSLT after creating the task, right? If I do I get the "Root element is missing".

Thankyou for the link

 
Dmitriy Benyuk
Reply

Hi Filip,
You can edit the XSLT file after creating the task, but you have to be careful about the changes in it, they can influence in the transformed xml file which is created after the xslt file applying. So the best way to avoid errors at the job execution is to create the job after finishing the xslt file that you need to use in it.

But it you need to change already existing xslt which is used in already existing job, then you need to edit the job after this xslt file fixing/editing. Try to open the job and check the mappings from source to destination.

 

You get the "Root element is missing" error because the xslt you used in this post was creating wrong xml file, that was the reason of this error.
You can check the transformed xml file by yourself, it is located in the "Files" folder and is called "xslTransformedInput.xml"
 

 
Filip Lundby
Reply

Hi Dmitriy

Okay, so now I've created an XSLT and testet it at xslttest.appspot.com (see attached). But now when I want to create the transform-task the source list is blank (see screenshot).

If I change back the XSLT to <xsl:copy-of select="." /> I see the source list. It's like it's already testing using my XSLT...? Is DW expecting the XSLT to look in certain way?

blanksource.jpg
 
Dmitriy Benyuk
Reply

Hi Filip,
The xml file for the import to DW should have the same format as is received from the export from DW, e.g. run some job to export data from DW to XML(use XML provider as destination) you will get the exported xml file, look at his content/structure. The same xml structure should be for the import.
So your xslt which is applied on your xml file should output the xml with the format/structure as you receive from the export.
For example here is a simple product xml that can be used for the import:
 

<?xml version="1.0" encoding="utf-8"?>
<tables>
	<table tableName="EcomProducts">
		<item table="EcomProducts">
			<column columnName="ProductID">
				<![CDATA[PROD1]]>
			</column>
			<column columnName="ProductNumber">
				<![CDATA[PRODUKT1]]>
			</column>
			<column columnName="ProductName">
				<![CDATA[PRODUKT1]]>
			</column>
		</item>				
	</table>
</tables>

 

 
Morten Bengtson
Reply

Hi Filip,

 

What you are trying to do was easy to set up in the previous Import/Export module, but as far as I can see it is impossible using Data Integration module.

 

Data Integration can import any XML by using XSLT to transform it into the specific format it expects (tables > table > item > column).

 

Data Integration can only export XML in the specific format (tables > table > item > column). There is no way to transform the output.

 

For exported data you are stuck with tables, items and columns in the XML, which makes it useless for many common integration tasks.

 

Please correct me if I'm wrong. I really hope that I am wrong. Oh God, please say it ain't so.

 

 
Morten Snedker
Reply

You are not wrong. However, we are aware of the missing functionality, so it is in the roadmap for soon to be.

 

Regards
God

 

 

 
Peter Bille Larsen
Reply

Is there anything we can do, to makes this possible, with implementation this week?

ie. exclusively on the clients solution (custom).

We are willing to use the dev program to speed the implementation up.

 

However, what we are trying to build is a feature within ecom systems, our alternative is to use the data list module, but then the costs of the feature will exceed competitors price, so we are pretty dependent on a fast solution.

Please help.

 

 
Morten Bengtson
Reply

God works in mysterious ways ;-)

 

If you just need to provide an XML feed, you can transform the XML when requested.

You can do that by using GetXml.aspx like this:

/Admin/Public/GetXml.aspx?XmlFile=/Files/Files/Integration/Products.xml&XsltFile=/Files/Files/Integration/Products.xslt

Where Products.xml contains the data exported by Data Integration and Products.xslt is used for transforming the data into the custom format you need.

 

You can also change the Content-Type response header by appending one more parameter - if you want to serve some specific standard format, like RSS...

/Admin/Public/GetXml.aspx?XmlFile=/Files/Files/Integration/Products.xml&XsltFile=/Files/Files/Integration/Products.xslt&ContentType=application/rss%2bxml

/Morten

 

 
Morten Bengtson
Reply

If you need to use the data on a page in Dynamicweb, you can use the module Content Integrator (free of charge) for transforming the exported XML.

 

/Morten

 
Peter Bille Larsen
Reply

Hi Morten,

Anyway, do you know if we can output a flat file with that link? the reason is that the price engines would ask for the link, and if there is 20.000 + products, there could be a potential time-out, which would make the engine pass on to the next shop.

So we would in best case need a flat XML file to send to the provider.

 

 
Jonas Dam
Reply

Hi Peter. 

One option is to create your own CustomXmlProvider, which inherits from the XmlProvider.

then you can:

public override bool RunJob(Job job, string logFile)

{

 

bool result = base.RunJob(job, logFile);

if (result)

    {

    //do whatever you need to do to the output  file -you can get an xmlreader by using:

// XmlReader.Create(WorkingDirectory + FileName)

//or do an xsltTransformation using:

//XslCompiledTransform oTransform = new XslCompiledTransform();
// oTransform.Load(WorkingDirectory + XslFile);
 
// oTransform.Transform(WorkingDirectory + _filename, WorkingDirectory + "xslTransformedInput.xml");

    }

return result;
}

The templates for custom providers is available in the VisualStudio templates which are available for download elsewhere on this site :)

 

Hope this is useful.

 

/Jonas

 

 

 
Peter Bille Larsen
Reply

Hi Jonas

Custom functionality is not within the budget frame, I have just heard from project management. It must be a build in functionality.

 

@God. whats you opinion on this following post? and the ETA? :-) any comments?  can we do anything from here. (funding).
http://developer.dynamicweb-cms.com/forum/integration-data-integration/xsl-file-for-xml-output.aspx

 

 
Peter Bille Larsen
Reply

Hi All.

I have just heard that Dataintegration is updated, to include XSLT in XML output, this week. So thats great news, which solves the problem.

Thank you all, for your help, effort and input.

//Peter

 
Kristian Knudsen
Reply
This post has been marked as an answer

Yes I can confirm that and the improvement (see screenshot) will be included in 8.1.3.0 which we release this week. 

XML_provider.png
Votes for this answer: 1

 

You must be logged in to post in the forum