RE: [xsl] generating id by calling template but how to use it at other places

Subject: RE: [xsl] generating id by calling template but how to use it at other places
From: "Roger Glover" <glover_roger@xxxxxxxxx>
Date: Thu, 6 Feb 2003 00:05:52 -0600
Jinesh Varia wrote:

> Please ignore the previous email this email contains
> proper question without any typos

You are closer to no typos, but not quite there yet...

> two unique problems:
>
> My XML is
> <publication pubid="0002">
> <author>steve lawer</author>
> ........
> <publication>
>
>
> I want my new XML as:
> <publication pubid="0002">
> ........
> </publication>
> <person perid="100000004"> <!-- new id generation -->
> <personname>steve lawer</personname>
> </person>
> <pubper> <!-- publication-person intersection -->
> <pubid>0002</pubid>
> <perid>100000004</perid>
> </pubper>
>
> My XSL is:
> <?xml version="1.0"?>
>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>  <xsl:output method="xml" indent="yes"/>
>
> <xsl:template match="publication">
>
> <publication>
> <xsl:copy-of select="@*|*[not(self::author or
> self::editor)]"/> <!-- this is just to cut the authors
> element-->
> </publication>
>
> <xsl:if test="author=not(.=preceding::author)"

I believe this line has a typo.  As it sits it compares the nodeset of all
authors under the current publication to the boolean value if the statement
"the current publication node is not one of the preceding author node".
That boolean value is always true, so whenever the publication has at least
one author the whole expression will be true.

I believe that you intended the line to read:

--------------
<xsl:if test="author[not(.=preceding::author)]"
--------------


> ><!-- this is so that we get unique author names:
> Please comment on this #####1-->

Okay, after we fix the typo it selects the right nodes, but it is not
structurally in the right place.  Rather than doing the author hunt on a per
publication basis, I would use a global variable to create and store a
temporary result tree fragment of "person" elements like this:

--------------
<!-- put this outside any template -->
<xsl:variable name="persons">
    <xsl:for-each select="//publication/author[not(.=preceding::author)]">
        <person>
            <xsl:attribute name="perid">
                <xsl:call-template name="generate-author-id"/>
            </xsl:attribute>
        </person>
    </xsl:for-each>
</xsl:variable>
--------------

I would then extract the "perid"s that I need when I need them.  You say
nothing about the order of elements in the result document.  I assume that
since <publication>, <person>, and <pubper> are now all peers, that they can
be placed into the result document in any order.  Of course, if there is a
strict order and you tell us what it is, we could help you achieve that too.

------ snip ------
> Please comment on ###1,

###1 was a typo, see above.


> ###3
> I want to know what select statement should I use?
> I thought using a
>
> <xsl:variable name="tempperid">
> <xsl:call-template name="generate-author-id" />
> </xsl:variable>
>
> and use $tempperid everywhere. But this does not work
> since the XSL is a decraraltive language and the value
> of the variable remains the same.

So what *I* would do instead is generate *ALL* the "perid"s (and the
"person" elements around them) in a global variable (see above) and extract
the "perid"s you need when you need them.

I would be glad to work up a some demo code for you (being out of work does
give me a fair amount of free time for this sort of thing) :-)-:.  But it is
nearly midnight on a cold night in Minnesota, so I am off to bed.  If you
don't have any better answers by (my) morning, I will be glad to see what I
can do for you.

-- Roger Glover
   glover_roger@xxxxxxxxx



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


Current Thread