Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 496
  • Last Modified:

XSL Transformation

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
paragpjoshi
Asked:
paragpjoshi
  • 11
  • 8
1 Solution
 
sweetfa2Commented:
Sample input and expected output files?
0
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Geert BormansCommented:
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
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
My bad, I did not spot the prodrefs, sorry about that, hang on a minute
0
 
Geert BormansCommented:
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
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
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
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
"Samgung" should be "Samsung" in the @name of the prodRef element
0
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
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
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
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
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
I don't need the XSLT for knowing what you are doing, I need the process that executes the XSLT
0
 
paragpjoshiAuthor Commented:
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
 
Geert BormansCommented:
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
 
Geert BormansCommented:
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

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 11
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now