Solved

XSL Transformation

Posted on 2010-11-11
20
468 Views
Last Modified: 2012-05-10
Hi,

I have an Input XML File - "Input XML File.xml".  This file contains a) Product/Product Group Hierarchy, and b) Individual Products within each Product Group.

Each Product Group XML tag defines the list of products within that group.  (E.g. "Nokia Handsets" product group has handsets Nokia E61 and Nokia E71)

I would like to use XSL and convert the input file into two separate output files as follows:

1. Output XML File - ProductGroups.xml: Containing the Product Groups

I will use the XML file using my application to display a product hierarchy as below.  [Please note, that I need help only in creating the Output XML file, the application already takes care of the rest.  The below hierarchy is shown just to give the overall picture]

E.g.

-> Handsets
   --> Nokia Handsets
       - Nokia E61
       - Nokia E71
   --> Samsung Handsets
       - Samsung Wave
       - Samsung Galaxy
-> Accesories
   --> Car Chargers
       - Nokia Car Chargers
       - Samsung Car Chargers


2. Output XML File - Products.xml: Containing individual products.

PS - I am attaching sample Input and expected Output files for ready reference.

Please could you help me with the XSL transformation to do this.

I appreciate your help!

Thanks,
PJoshi
0
Comment
Question by:paragpjoshi
  • 11
  • 8
20 Comments
 
LVL 17

Expert Comment

by:sweetfa2
ID: 34116866
Sample input and expected output files?
0
 

Author Comment

by:paragpjoshi
ID: 34118697
Not sure how the attachments are missing!

I am attaching the files again.

Thanks,
PJoshi
Input-XML-File.xml
Output-XML-File---ProductGroups.xml
Output-XML-File---Products.xml
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34118882
Here is your first XSLT

The next one is very similar and you can do that yourself, no?
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

    version="1.0">

    <xsl:output indent="yes"/>

    <xsl:template match="release">

        <ProductGroupList>

            <xsl:apply-templates select="productDefinition[@type='Product_Group']"/>

        </ProductGroupList>

    </xsl:template>

    <xsl:template match="productDefinition">

        <ProductGroup>

            <ProductGroupID><xsl:value-of select="attribute[@name = 'GroupID']"/></ProductGroupID>

            <ParentProductGroupID><xsl:value-of select="attribute[@name = 'ParentGroupID']"/></ParentProductGroupID>

            <Description><xsl:value-of select="@name"/></Description>

        </ProductGroup>

    </xsl:template>

</xsl:stylesheet>

Open in new window

0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34119049
Well, there is an issue with the second output XML
There is no relation in the XML that indicates that the Nokia E61 belongs to the Nokia Handsets
I think you are missing identifiers in your XML
If this is a relational database export,
make sure you copy the keys
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

    version="1.0">

    <xsl:output indent="yes"/>

    <xsl:template match="release">

        <ProductGroupList>

            <xsl:apply-templates select="productDefinition[@type='Device' or @type='Accessory']"/>

        </ProductGroupList>

    </xsl:template>

    <xsl:template match="productDefinition">

        <Product>

            <ProductID><xsl:value-of select="attribute[@name = 'Barcode']"/></ProductID>

            <ProductGroupID>???</ProductGroupID>

            <Description><xsl:value-of select="@name"/></Description>

            <StartDate><xsl:value-of select="attribute[@name = 'StartDate']"/></StartDate>

            <ReturnPeriod><xsl:value-of select="attribute[@name = 'Return Period']"/></ReturnPeriod>

        </Product>

    </xsl:template>

</xsl:stylesheet>

Open in new window

0
 

Author Comment

by:paragpjoshi
ID: 34119235
The relation between Nokia and Nokia E61 is to be established from the following tag in the Input XML.  Is this possible?

    <productDefinition name="Nokia Handsets" type="Product_Group">
        <attribute name="GroupID">Nokia Handsets</attribute>
        <attribute name="ParentGroupID">Handsets</attribute>
        <prodRef name="Nokia E61" type="Device" />
        <prodRef name="Nokia E71" type="Device" />
    </productDefinition>

Thanks for your help!
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34119254
My bad, I did not spot the prodrefs, sorry about that, hang on a minute
0
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 500 total points
ID: 34119270
So, here you go
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

    version="1.0">

    <xsl:output indent="yes"/>

    <xsl:key name="group" match="productDefinition" use="prodRef/@name"/>

    <xsl:template match="release">

        <ProductGroupList>

            <xsl:apply-templates select="productDefinition[@type='Device' or @type='Accessory']"/>

        </ProductGroupList>

    </xsl:template>

    <xsl:template match="productDefinition">

        <Product>

            <ProductID><xsl:value-of select="attribute[@name = 'Barcode']"/></ProductID>

            <ProductGroupID><xsl:value-of select="key('group', @name)/@name"/></ProductGroupID>

            <Description><xsl:value-of select="@name"/></Description>

            <StartDate><xsl:value-of select="attribute[@name = 'StartDate']"/></StartDate>

            <ReturnPeriod><xsl:value-of select="attribute[@name = 'Return Period']"/></ReturnPeriod>

        </Product>

    </xsl:template>

</xsl:stylesheet>

Open in new window

0
 

Author Comment

by:paragpjoshi
ID: 34120445
Hi,

Thank you very much for this.  It worked!  However, two minor issues which I observed.

1.  I could redirect the output into the ProductGroup.xml output file.  However, the Product.xml output file is not getting generated (even though output can be seen on console).  

2. For ProductId=1234567890444 (Samsung Galaxy), the ProductGroup (Samsung Handsets) does not get populated in the output file.

Thanks once again,
PJoshi
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34120536
1. I consider that outside this question. It means that whatever architecture you have to get this done, is redirecting the stream to the wrong place.
So you need to closely look into that yourself

2. I know, that is an error in your source XML
 <prodRef name="Samgung Galaxy" type="Device" />
Look at that. The @name has a typo (missing 's')
0
 

Author Comment

by:paragpjoshi
ID: 34121581
Hi,

Apologies, I am probably asking a very silly question.

Where is the missing 's' ?

Sorry, but I cant locate the missing 's'!

Thanks,
PJoshi
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34121731
"Samgung" should be "Samsung" in the @name of the prodRef element
0
 

Author Comment

by:paragpjoshi
ID: 34127073
Oh yes!  I can't believe I did not spot that!  Thanks once again!

Could you help as to how to create two files?  I am not able to create the Product output file.  I am only able to create the productgroup xml.  

PS - I am accepting the solution.

Thank a lot once again,
Pjoshi
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34127348
Well, without more context, I can't help you.
There are a zillion ways for running an XSLT.
You need to be aware that you need two parallel execution steps,
so, which ever way you run the XSLT, you need to do that twice.

Can you tell me more about the architecture?
0
 

Author Comment

by:paragpjoshi
ID: 34133068
Hi,  I have been able to successfully create both the output files.  Thanks for your help!

I had to parse the input xml twice.  Once for product xml and once for product group xml.  Is it possible to create both the output files with only one parse?

Thanks,
Pjoshi
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34135059
Hi Pjoshi,

Still I don't have the context to answer that question.
I am still unaware on how you do the transforms.

XSLT2 has a concept of writing multiple files in one pass.
But that will mean rewriting the XSLTs completely

You have 2 XSLTs and expect 2 output files.
You should launch two processes.
But depending on how you execute the XSLT,
you can avoid having to parse the source twice.
And you could compile the XSLTs

but for that, I need a lot more detail
0
 

Author Comment

by:paragpjoshi
ID: 34144953
Hi,

I am attaching the XSLT that I am using to create the two output files.  I am having to parse the input file twice to create the two output files.

1. Is there any way you could suggest to do this in one parse?

2. Also, one more question (not related to this one, so let me know if you want me to raise this as a new question).  How do I modify the XSLT to output only 1000 products in one file (i.e. create new Product Output file for every 1000 products)

Thanks for your help in advance!

Thanks,
PJoshi
Create-Product-Files.txt
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34145535
I don't need the XSLT for knowing what you are doing, I need the process that executes the XSLT
0
 

Author Comment

by:paragpjoshi
ID: 34153636
Hi,

Apologies! Its my fault! I did not realise that you wanted the process that executes the XSLT.

Please find attached Java program which uses the XSLT to do the transformation and create the output files.

Thanks,
PJoshi
ProductTransformer.java
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34153771
you could restructure your ProductTransformer method so that it takes 2 XSL as a parameter,
make two transformers in the method and run both transformers on the same input
instead of using the output stream System.out, use two file references for the output, soit gets piped in the right output file
that way, you have only one call to the method and you only need to parse the input file once

I am not a Java programmer, so you need to do that bit yourself
(I just now realised you were doing this in Java)

To answer your other question.
Usual approach for that is
- First (by using selectNodes with an XPath that gets the nodes) you can count (without XSLT) how many nodes there are in the document
- Then calculate how many calls you need to make to teh XSLT (eg. if you have 2559 records, you need a call for 1-1000, 1001-2000, 2000-2559)
- pass in two parameters eg. 1,1000 for the first call
- in the XSLT select the nodes with the lower and upper boundary as found in the parameters

The bulk of the work is in the Java, not in the XSLT for that
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 34153805
Aha, I see you are using Xalan, did not spot the redirect:open and redirect:write before.
Does that work? I mean, did you pick the code up somewhere, without realising that you are not using Xalan?
Or did you test the redirect to work?

In case you are successfully using redirect, you can merge the two XSLTs that I did before and create all the stuff in one go

please let me know:
- that you are using Xalan and can safely use redirect:open (if you currently don't you can bind the java to it

please also send me the two XSLTs as you currnetly use them, so I can wrap them together

No need to change the java then
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Styling your websites can become very complex. Here I'll show how SASS can help you better organize, maintain and reuse your CSS code.
In this article you will learn how to create a free basic website on Bitbucket, a git service provider. Polymer creates dynamic HTML components, which allow more flexibility than static HTML. This tutorial uses Ubuntu Linux but can also be done on W…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now