Solved

XSLT, Identity transformation and XML

Posted on 2004-09-24
8
686 Views
Last Modified: 2008-03-10
Hi,

Today I use identity transform. to filter elements from my original XML file and create XML output file.
I have created two XSLTs (base.xslt and filter.xslt), where base.xslt does the identity transformation and filter.xslt defines filtering rules and templates.

What I basically want is to filter elements of type "sub" and sort them under one parent node and make selections of type "main" and sort them under another parent node. One parent node for each category. (see in Filtered XML how output shoul look like).

My input XML looks like:

[Original XML]

<Documents>
    <Document chapter="1" title="title 1" href="file1.xml">
          <Article title="1.1" info="sub"/>
          <Article title="1.2" info="main"/>          
     </Document>
    <Document chapter="2" title="title 2" href="file2.xml">
          <Article title="2.1" info="sub"/>
          <Article title="2.2" info="main"/>          
     </Document>
</Documents>


[Filtered XML SHOULD LOOK LIKE]

<Documents>
    <Document name="main">
          <Article title="1.2" info="main"/>
          <Article title="2.2" info="main"/>
     </Document>
    <Document name="sub">
          <Article title="1.1" info="sub"/>        
          <Article title="2.1" info="sub"/>          
     </Document>
</Documents>


[base.xslt]

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   
     <!-- Import filter rules -->
        <xsl:include href="filter.xslt"/>

     <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
     <xsl:template match="node() | @*">
          <xsl:copy>
               <xsl:apply-templates select="node() | @*"/>
          </xsl:copy>
     </xsl:template>
</xsl:stylesheet>


[filter.xslt]

<?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" version="1.0" encoding="UTF-8" indent="yes"/>
            <xsl:template match="Doc[not(@info='main')][not(@info='sub')]"/>
</xsl:stylesheet>


thnx.

-J
0
Comment
Question by:morpheous_
  • 3
  • 3
8 Comments
 
LVL 15

Expert Comment

by:dualsoul
ID: 12146895
hm...morpheous_ , but this is outputs:

<Documents>
    <Document name="main">
          <Article title="1.2" info="main"/>
          <Article title="2.2" info="main"/>
     </Document>
    <Document name="sub">
          <Article title="1.1" info="sub"/>        
          <Article title="2.1" info="sub"/>          
     </Document>
</Documents>


 - doesn't it what you want? not?
0
 

Author Comment

by:morpheous_
ID: 12147911
I want output to look something like that.
I would like to create parent nodes that group filtered elements, so each element group (e.g. info="main") is sorted under one parent node, and other element group (e.g. info="sub") is sorted under other parent node.

The above is just the example how it supposed to look like, if I send the ORIGINAL.XML trough  FILTER.XML.
So, I would need to define rules in Filter.xml (or similar) that create output like the one below:

<Documents>
    <Document name="main">
          <Article title="1.2" info="main"/>
          <Article title="2.2" info="main"/>
     </Document>
    <Document name="sub">
          <Article title="1.1" info="sub"/>        
          <Article title="2.1" info="sub"/>          
     </Document>
</Documents>
0
 

Author Comment

by:morpheous_
ID: 12156327
what differs is that I would like to generate parent nodes groups automatically based on the filtered elements.
e.g. if elements info=main are filtered, then they should be grouped under it's own parent node group called "main" (like in the output example above), same with the other filtered element "sub" should have it's own group.

So, the pseudo should look something like this:

1. filter all elements where attribute info="main"
2. create parent node called "main" for elements where info="main"
3. place elements (Article) of attribute info="main" under parent node "main"

and so on iterate, untill original, input XML is filtered completely of the keywords located in filter.xslt

 <xsl:template match="Doc[not(@info='main')][not(@info='sub')]"/>



    <Document title="main">
          <Article title="1.2" info="main"/>
          <Article title="2.2" info="main"/>
     </Document>
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 15

Expert Comment

by:dualsoul
ID: 12167894
it seems i confused, can you post sample and result for it.
0
 

Accepted Solution

by:
morpheous_ earned 0 total points
ID: 12178747
I wanted to group Article elements by their info attribute.

I have found a solution.

By using Muenchian Method, I am able to group elements under parent nodes created from the filtered elemtens groups.

<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:key name="by-info" match="Article" use="@info"/>
   <xsl:template match="/Documents">
       <Documents>
           <xsl:for-each select="Document/Article[count(.|key('by-info', @info)[1])=1]">
               <Document name="{@info}">
                   <xsl:copy-of select="key('by-info', @info)"/>
               </Document>
           </xsl:for-each>
       </Documents>
   </xsl:template>
</xsl:stylesheet>


More about Muenchian method @ http://www.jenitennison.com/xslt/grouping/muenchian.html


Regards,

-xrow
0
 
LVL 15

Expert Comment

by:dualsoul
ID: 12198688
morpheous_ , i'm glad you've found a solution yourself.

Sorry, i was really busy at work, and was unable to dig your problem.
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

778 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