import Walker

Subject: import Walker
From: "Benoit Cerrina" <benoit.cerrina@xxxxxxxxxxx>
Date: Mon, 23 Oct 2000 20:18:38 +0200
Hi (this is my third posting, I hope it will get through),
here is my problem:
I have some xml documents with the equivalent of an import clause in java,
essentially it could look like this
----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


Current Thread
  • import Walker
    • Benoit Cerrina - Mon, 23 Oct 2000 20:18:38 +0200 <=