[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Data Recursion created by References

Subject: Data Recursion created by References
From: "bix xslt" <bix_xslt@xxxxxxxxxxx>
Date: Thu, 10 Apr 2003 20:47:48 +0000
x param
All,

This question is mostly a design question. I'm wondering if someone else has run into a similar problem that I'm having with data that contains recursion within it. The format of my data is something like the following:

<object name="someObjectName">
 <childRef name="someReferenceToAnObject"/>
</object>

So, for a simple example I have the following. Note that to make this a well formed document, the top node contains all other nodes, but the referencing still applies.

<object name="a">
 <childRef name="b"/>
 <childRef name="c"/>
 <object name="b"><childRef name="a"/></object>
 <object name="c"><childRef name="d"/></object>
 <object name="d"><childRef name="b"/></object>
</object>

Specifically, I want to follow the data's path through a portion of the recursion. For example, suppose a webpage displays information about object 'a', and a user wishes to follow a link to the child node 'c'. The path to the object 'c' would be as follows:
a -> c


If the user continued to follow the child references, the user might end up with the following path to 'b':
a -> c -> d -> b


Alternatively, the user might just end up wanting to follow the reference to 'b' initially:
a -> b


Is there a mechanism/algorithm for distinguishing between these two paths that can be implemented within xslt?

If I modified the xml slightly, there is an alternative problem:
<object name="a">
 <childRef name="b"/>
 <childRef name="c"/>
 <object name="b"><childRef name="c"/></object>
 <object name="c"><childRef name="d"/></object>
 <object name="d"/>
</object>

How do I distinguish between:
   a -> b -> c -> d
and
   a -> d

Currently, I reference the objects through a key that identifies each object individually, but unfortunately this doesn't help me determine which path was used. What I'd like to do is reference the object by it's path through the child references as opposed to the unique object. I believe there is a solution that addresses both problems, but I haven't found it yet. Has anyone run across a problem similar to this that might be able to provide some help?

Thanks,
bix

I orginally designed my xsl without taking multiple references to the same object into consideration.
Within the XSL that follows, this line enforces just a single reference:
<x:with-param name="currNode" select="exslt:node-set($parentNodes)[1]"/>



The following is my XSL. <!-- xmlns:exslt="urn:schemas-microsoft-com:xslt" --> <!-- xmlns:exslt="http://www.exslt.org" -->

<x:stylesheet version="1.0"
 xmlns:x="http://www.w3.org/1999/XSL/Transform"
 xmlns:exslt="urn:schemas-microsoft-com:xslt"


<x:output indent="yes" method="html"/>


 <x:key name="objectsKey" match="object" use="@name"/>
 <x:key name="childrenKey" match="object" use="childRef/@name"/>
 <x:param name="startNodeName" select="'d'"/>
 <x:param name="topNodeName" select="'a'"/>
 <x:param name="startNode" select="//object[@name = $startNodeName]"/>
 <x:param name="topNode" select="//object[@name = $topNodeName]"/>

 <x:attribute-set name="hiddenTable">
   <x:attribute name="border">0</x:attribute>
   <x:attribute name="cellspacing">0</x:attribute>
   <x:attribute name="cellpadding">0</x:attribute>
 </x:attribute-set>

 <x:attribute-set name="fillWindow">
   <x:attribute name="style">margin: 0;</x:attribute>
 </x:attribute-set>

<x:template match="/">
<x:element name="startNodeName">
<x:attribute name="name"><x:value-of select="$startNodeName"/></x:attribute>
</x:element>
<x:apply-templates select="object"/>
</x:template>


 <x:template match="object">
   <x:element name="html">
     <x:element name="head">
       <x:element name="title">Autogenerated Webview</x:element>
       <x:element name="style">
         <![CDATA[
           a {text-decoration:none}
         ]]>
       </x:element>
       <x:element name="script">
         <![CDATA[
   var xmlObj = null;
   var xslObj = null;
   var xformer = null;

   function getXMLObj(xmlFileName) {
       xmlObj = new ActiveXObject("Msxml2.DOMDocument.4.0");
       xmlObj.async = false;
       xmlObj.validateOnParse = true;
       xmlObj.load(xmlFileName);
       return xmlObj;
   }

   function getXSLObj(xslFileName) {
       xslObj = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.4.0");
       xslObj.async = false;
       xslObj.validateOnParse = true;
       xslObj.load(xslFileName);
       return xslObj;
   }

   function getTransformer(xmlObject, xslObject) {
       var template = new ActiveXObject("MSXML2.XSLTemplate.4.0");
       template.stylesheet = xslObject.documentElement;
       var transformer = template.createProcessor();
       transformer.input = xmlObject;
       return transformer;
   }

   function init()
   {
       xmlObj = getXMLObj("temp.xml");
       xslObj = getXSLObj("temp.xsl");
   }

   function refresh(id,w)
   {
       var xformer = getTransformer(xmlObj,xslObj);
       xformer.addParameter("startNodeName", id, "");
       xformer.transform();
       w.write(xformer.output);
       w.close();
   }
         ]]>
       </x:element>
     </x:element>
     <x:element name="body" use-attribute-sets="fillWindow">
       <x:attribute name="onload">javascript:init()</x:attribute>
       <x:element name="table" use-attribute-sets="hiddenTable">
         <x:element name="tr">
           <x:element name="td">
             <x:call-template name="makePath">
               <x:with-param name="currNode" select="$startNode"/>
             </x:call-template>
           </x:element>
         </x:element>
       </x:element>
     </x:element>
   </x:element>
 </x:template>

<x:template name="makePath">
<x:param name="topNode" select="$topNode"/>
<x:param name="currNode" select="."/>
<x:param name="currNodeName" select="exslt:node-set($currNode)/@name"/>
<x:param name="parentNodes" select="key('childrenKey', $currNodeName)"/>
<x:choose>
<x:when test="(exslt:node-set($parentNodes)) or (generate-id($topNode) != generate-id($currNode))">
<x:call-template name="makePath">
<x:with-param name="currNode" select="exslt:node-set($parentNodes)[1]"/>
</x:call-template>
<x:call-template name="addSpacer"/>
<x:call-template name="showNode">
<x:with-param name="node" select="$currNode"/>
</x:call-template>
</x:when>
<x:otherwise>
<x:call-template name="showNode">
<x:with-param name="node" select="$currNode"/>
</x:call-template>
</x:otherwise>
</x:choose>
</x:template>


<x:template name="showNode">
<x:param name="node" select="."/>
<x:element name="a">
<x:attribute name="href">javascript:refresh('<x:value-of select="exslt:node-set($node)/@name"/>',this.document)</x:attribute>
<x:element name="font">
<x:attribute name="face">Arial</x:attribute>
<x:value-of select="exslt:node-set($node)/@name"/>
</x:element>
</x:element>
</x:template>


 <x:template name="addSpacer">
   &#160;
   <x:element name="font">
     <x:attribute name="face">Wingdings</x:attribute>&#xF0;</x:element>
   &#160;
 </x:template>
</x:stylesheet>


_________________________________________________________________
The new MSN 8: smart spam protection and 2 months FREE* http://join.msn.com/?page=features/junkmail



XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.