This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

import Traversal



********doc a*******
<?xml version="1.0" encoding="UTF-8"?>
<doc name="a">
    <import name="b"/>
    <import name="c"/>
 <object id="1" ref="2" payload="A"/>
</doc>
****end doc a***********

****doc b***********
<?xml version="1.0" encoding="UTF-8"?>
<doc name="b">
 <import name="a"/>
 <object id="2" ref="3" payload="B"/>
 <object id="3" payload="C"/>
</doc>
****end doc b***********

****doc c***********
<?xml version="1.0" encoding="UTF-8"?>
<doc name="c">
    <import name="b"/>
</doc>
****end doc c***********
So we have an import tree which looks like:
a---->b---->a
|---->c---->b---->a

Now I'm processing the document "a"
I'd like to get:
<object id=1>
 ABC
</object>
or in english each time I encounter an object I need to print out it's
payload and the payload of its reference and its reference's reference...
My problem is that I know how to do a depth first transversal of the import
graph of document, I even know how to avoid problems with the cycle which
appears due to the import of a in b, however I don't know how to deal with
the fact that both branches have a part in common. This is actually the same
problem as with multiinheritance in c++ and the losange pattern.
All my efforts have yielded the following result:
<object id=1>
 ABCBC
</object>


Benoit

PS:
this is what my stylesheet looks like:

******importWalker.xsl*******
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
 <xsl:output method="xml" indent="yes"/>
 <!--main template-->
 <xsl:template match="doc">
  <xsl:apply-templates select="object"/>
 </xsl:template>

 <xsl:template match="object">
  <object id="{@id}">
   <xsl:apply-templates select="." mode="payload"/>
  </object>
 </xsl:template>


 <xsl:template match="object" mode="payload">
  <!--passthrough parameter to the walker-->
  <xsl:param name="visitedDocs" select="/.."/>
   <xsl:value-of select="@payload"/>
   <xsl:if test="@ref">
    <xsl:call-template name="importWalker">
     <xsl:with-param name="visitedDocs" select="$visitedDocs"/>
     <xsl:with-param name="target" select="@ref"/>
    </xsl:call-template>
   </xsl:if>
 </xsl:template>

 <xsl:template name="importWalker">
  <xsl:param name="visitedDocs" select="/.."/>
  <xsl:param name="target"/>
  <xsl:variable name="newVisitedDocs" select="$visitedDocs | /doc/@name"/>
  <xsl:variable name="targetObj" select="//object[@id = $target]"/>
  <xsl:choose>
   <!--first test if the object is in this document I know // is ugly in
truth I use key-->
   <xsl:when test="$targetObj">
    <!--found it print payloads and recurse-->
    <xsl:apply-templates select="$targetObj" mode="payload">
     <xsl:with-param name="visitedDocs" select="$newVisitedDocs"/>
    </xsl:apply-templates>
   </xsl:when>
   <xsl:otherwise>
    <!--iterate and recurse other all imports-->
    <xsl:for-each select="document(/doc/import/@name, .)">
     <!--check for import cycles-->
     <xsl:variable name="docName" select="/doc/@name"/>
     <xsl:if test="not($newVisitedDocs[string(.) = string($docName)])">
      <xsl:call-template name="importWalker">
       <xsl:with-param name="target" select="$target"/>
       <xsl:with-param name="visitedDocs" select="$newVisitedDocs"/>
      </xsl:call-template>
     </xsl:if>
    </xsl:for-each>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>
******end importWalker.xsl*******


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]