?
Solved

XSLT, Identity transformation and XML

Posted on 2004-09-24
8
Medium Priority
?
701 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_
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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

Automating Terraform w Jenkins & AWS CodeCommit

How to configure Jenkins and CodeCommit to allow users to easily create and destroy infrastructure using Terraform code.

Question has a verified solution.

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

The Confluence of Individual Knowledge and the Collective Intelligence At this writing (summer 2013) the term API (http://dictionary.reference.com/browse/API?s=t) has made its way into the popular lexicon of the English language.  A few years ago, …
Create a Windows 10 custom Image with custom task bar and custom start menu using XML for deployment.
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses

777 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