Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 18th, 2008, 02:35 AM
Registered User
 
Join Date: Jun 2008
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default restructuring xml

Hi,

I can do basic xml translations but I've become stuck when trying to restructure an xml document.

The document is in the following format
Code:
<model>
 <root node name="example" ID="4" type="A"/>
  <item>
   <name>xyz</name>
   <ID>7</ID>
   <type>A</type>
   <parentname>example</parentname>
   <parentID>4</parentID>
  </item>
  <item>
   <name>bob</name>
   <ID>5</ID>
   <type>B</type>
   <parentname>example</parentname>
   <parentID>4</parentID>
  </item>
  <item>
   <name>cat</name>   
   <ID>10</ID>
   <type>A</type>
   <parentname>xyz</parentname>
   <parentID>7</parentID>
  </item>
</model>
Basically you have a model and all these items including a root item listed. I want to restructure this so items are contained within their parents such to this

Code:
<model>
 <nonterm name="example" ID="4">
  <item>
   <name>xyz</name>
   <ID>7</ID>
   <type>A</type>
   <parentname>example</parentname>
   <parentID>4</parentID>
  </item>
  <item>
   <name>bob</name>
   <ID>5</ID>
   <type>B</type>
   <parentname>example</parentname>
   <parentID>4</parentID>
  </item>
 </nonterm>

 <nonterm name="xyz" ID="7">
  <item>
   <name>cat</name>
   <ID>10</ID>
   <type>A</type>
   <parentname>xyz</parentname>
   <parentID>7</parentID>
  </item>
 </nonterm>

</model>
Any ideas what the best way to do this would be? This is just an example of the format. Just a note that the original order and number of the items essentially has not order with respect to hierarchy.

Thanks in advance.

 
Old June 18th, 2008, 03:19 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The basic approach to this is to do a recursive descent using xsl:apply-templates in exactly the same way as you would normally, except that you apply-templates to the logical children of a node instead of the physical children. In your example you can find the logical children of the context <item> element using <xsl:apply-templates select="key('parent', ID)"/> where the key is defined as <xsl:key name="parent" match="item" use="parentID"/>.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 18th, 2008, 05:53 AM
Authorized User
 
Join Date: May 2008
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
Default

maybe it is not the best approach, but it is giving the needed result:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="parent" match="item|root" use="ID"/>
    <xsl:template match="model">
        <model>
            <xsl:apply-templates select="item/ID|root/@ID"/>
        </model>
    </xsl:template>
    <xsl:template match="item/ID|root/@ID">
        <xsl:if test="count(//item[parentID=current()])>0">
            <nonterm ID="{current()}">
                <xsl:attribute name="name">
                    <xsl:choose>
                        <xsl:when test="name(..)='root'">
                            <xsl:value-of select="../@name"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="../name"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:attribute>
                <xsl:copy-of select="//item[parentID=current()]"/>
            </nonterm>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
 
Old June 18th, 2008, 06:37 AM
Registered User
 
Join Date: Jun 2008
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks to the first and second poster. The first poster for the right idea and the second poster who came in with a solution as I was struggling with how to use the key function.

Thank you. Works well!

 
Old June 18th, 2008, 06:48 AM
Authorized User
 
Join Date: May 2008
Posts: 32
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:...and the second poster who came in with a solution as I was struggling with how to use the key function.
well, actually, my example is not using key function at all.
<xsl:key ... /> is redundantly left there by me after my attempts to implement it through key() func.
so you can erase it without any harm to the solution.






Similar Threads
Thread Thread Starter Forum Replies Last Post
SQL Server 2005 XML: FOR XML PATH -> cdata? stoves SQL Server 2005 1 July 8th, 2008 02:40 AM
Creating XML doc ; writing string(xml format) into KamalRaturi XML 5 May 28th, 2008 05:51 AM
VB.net, adding XML data to an existing XML file saikoboarder XML 11 April 17th, 2008 04:19 PM
xml invalid top level from ASP write XML(solution) g000we XML 0 August 9th, 2006 03:56 AM
DTS Package, XML task. Read XML file and store it Victoria SQL Server DTS 0 July 24th, 2006 02:43 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.