This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
import Walker
- To: <xsl-list at mulberrytech dot com>
- Subject: import Walker
- From: "Benoit Cerrina" <benoit dot cerrina at writeme dot com>
- Date: Mon, 23 Oct 2000 20:18:38 +0200
- Reply-To: xsl-list at mulberrytech dot com
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