You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Gary L Peskin <ga...@firstech.com> on 2000/10/24 21:24:00 UTC

Re: import Traversal

Benoit Cerrina wrote:
> Now I'm processing the document "a"
> I'd like to get:
> <object id=1>
>  ABC
> </object>

Benoit --

This will produce the results you desired for the input you supplied.  I
took a little different approach which required the nodeset extension. 
First, I navigate through all of the doc elements in the various
documents and build a nodeset consisting of all of the object elements. 
Then, I process the object elements in the main document but do not
process multiple object elements with the same id.

If you want to have multiple object elements with the same id, I think
you could jazz the stylesheet up a little bit to create object elements
which have the source document as an attribute or value.  Then, you can
eliminate elements if they come from the same document, using the
Muenchian method.  If you're interested in this and can't work it out,
let us know.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:nodeset="org.apache.xalan.xslt.extensions.Nodeset"
  exclude-result-prefixes="nodeset">

<!--main template-->

<xsl:template match="/">
  <!-- Step one:  Gather all object elements -->
  <xsl:variable name="all-objects">
    <xsl:apply-templates select="doc"/>
  </xsl:variable>

  <!-- Step two:  Process object elements from the primary document -->
  <xsl:apply-templates select="doc/object">
    <xsl:with-param name="objects"
select="nodeset:nodeset($all-objects)/object"/>
  </xsl:apply-templates>
</xsl:template>

<!-- This template accumulates all of the option elements -->
<xsl:template match="doc">
  <xsl:param name="visitedDocs" select="empty"/>
  <xsl:variable name="imported-objects">
    <xsl:apply-templates select="document(import/@name[not(. =
$visitedDocs)])/doc">
      <xsl:with-param name="visitedDocs" select="$visitedDocs | @name"/>
    </xsl:apply-templates>
  </xsl:variable>
  <xsl:copy-of select="object | nodeset:nodeset($imported-objects)"/>
</xsl:template>

<!-- This template processes the top object elements -->
<xsl:template match="object">
  <xsl:param name="objects"/>
  <object id="{@id}">
    <xsl:value-of select="@payload"/>
    <xsl:apply-templates select="$objects[@id = current()/@ref][1]"
mode="payload">
      <xsl:with-param name="objects" select="$objects"/>
    </xsl:apply-templates>
  </object>
</xsl:template>

<!-- And this template processes the referred-to object elements -->
<xsl:template match="object" mode="payload">
  <xsl:param name="objects"/>
  <xsl:value-of select="@payload"/>
  <xsl:apply-templates select="$objects[@id = current()/@ref][1]"
mode="payload">
    <xsl:with-param name="objects" select="$objects"/>
  </xsl:apply-templates>
</xsl:template> -->

</xsl:stylesheet>

Gary

Re: import Traversal

Posted by Gary L Peskin <ga...@firstech.com>.
Benoit Cerrina wrote:
>     according to the spec an easy way to initialize a parameter to the empty
> nodeset is using the select="/.." expression (if there are nodes named empty
> select="empty" does not work :-) )

Thanks.  I knew this at one point but then forgot it.  Thanks for
allowing me to relearn it.

Glad my feeble attempt was able to stimulate some ideas.

Gary

Re: import Traversal

Posted by Benoit Cerrina <be...@writeme.com>.
Hi Gary,
first thanks a lot,

> If you want to have multiple object elements with the same id,

I definitely do not want multiple object elements with the same id, since
part of the knowledge I have of the documents I'm manipulating is that it
cannot (shouldnot but if it does we have incoherent data, might as well keep
the first one) happen.
Now I'm back to my earlier performance problem, the documents which I'm
manipulating are quite large and my real stylesheet quite complexe and I'm
not sure how efficient it would be to do it your way. However that made me
think of another way of doing it, I'll send an english description of it:
Basically i can first traverse all the documents like you did but this time
hunting all the import statements, then I use the nodeset extension to turn
it into a nodeset and allow further processing. Then when I need to get an
object I traverse the list of imports to process (now it is a list not a
tree which makes all the difference since I can use the $visited-document
trick to make sure I traverse them only once) and I gather all objects with
the appropriate ids in all imported documents.
A few more remark about your stylesheet:
    according to the spec an easy way to initialize a parameter to the empty
nodeset is using the select="/.." expression (if there are nodes named empty
select="empty" does not work :-) )
    I had completely forgotten the peculiar definition of = between nodeset,
you reminded me of it and it will simplify my sheets.
Benoit