Solved

XSLT, Identity transformation and XML

Posted on 2004-09-24
8
694 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
Is Your DevOps Pipeline Leaking?

Is your CI/CD pipeline a hodge-podge of randomly connected tools? You’ve likely got a tool to fix one problem & then a different tool to fix another, resulting in a cluster of tools with overlapping functionality. Learn how to optimize your pipeline with Gartner's recommendations

 
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

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
Create a Windows 10 custom Image with custom task bar and custom start menu using XML for deployment.
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …

726 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