Hi,
I apologize for the length of the message. I have included XML, XSL, and
HTML snippets, so it's rather long. I also apologize for posting from
Lotus Notes, but I don't have and can't get a different e-mail program
here at my client site (the IT department frowns on anything but Notes). I
hope using Notes won't cause too much trouble.
To summarize the problem, I have identical elements (but they do have
different parent elements), and I am trying to get cross-references to
these identical elements with generate-id(). I've solved the problem
without generate-id() by concatenating a unique identifier from the titles
of the elements (child and parent). I've also solved the problem of
cross-references with a key and generate-id() - that's the solution I use
for production documents at present. However, that system does not allow
two elements to have identical titles. I would like to remove that
limitation and still use generate-id() - rather than having to key in a
long identifier for each cross-reference.
The following XML structure represents the problem:
<book>
<chapter title="Chapter 1">
<paragraph>The remainder of this book contains the following
material:</paragraph>
<list type="bulleted">
<listitem><ref target="chapter|Chapter 2">Chapter 2</ref>
<list type="bulleted">
<listitem><ref target="chapter|Chapter
2/topic|Introduction">Introduction</ref></listitem>
</list>
</listitem>
<listitem><ref target="chapter|Chapter 3">Chapter 3</ref>
<list type="bulleted">
<listitem><ref target="chapter|Chapter
3/topic|Introduction">Introduction</ref></listitem>
</list>
</listitem>
</list>
</chapter>
<chapter title="Chapter 2">
<topic title="Introduction"/>
</chapter>
<chapter title="Chapter 3">
<topic title="Introduction"/>
</chapter>
</book>
As you can see, some elements (<topic title="Introduction"/>) are
identical. However, they are the children of non-identical elements
(<chapter title="Chapter 2"/> and <chapter title="Chapter 2/">).
I've tried all kinds of things, but I can't get generate-id() to give me
the same path that it assigns to the referenced element. Just so you'll
have something to work with and get an idea of my thinking (wrong as it
is), here's the current stylesheet (representing the last of MANY failed
ideas) :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="chapter">
<h1><a name="{generate-id()}"/><xsl:value-of select="@title"/></h1>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="list">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="listitem">
<li><xsl:apply-templates/></li>
</xsl:template>
<xsl:template match="paragraph">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="ref">
<xsl:variable name="reftext">
<xsl:call-template name="makeRef">
<xsl:with-param name="inString" select="@target"/>
</xsl:call-template>
</xsl:variable>
<a href="#{generate-id(//$reftext)}"><xsl:value-of select="."/></a>
</xsl:template>
<xsl:template match="topic">
<h3><a name="{generate-id()}"><xsl:value-of select="@title"/></a></h3>
<xsl:apply-templates/>
</xsl:template>
<xsl:template name="makeRef">
<xsl:param name="inString"/>
<xsl:choose>
<xsl:when test="contains($inString, '/')">
<xsl:variable name="thisPart" select="substring-before($inString,
'/')"/>
<xsl:value-of
select="substring-before($thisPart,'|')"/>[(_at_)title='<xsl:value-of
select="substring-after($thisPart, '|')"/>']/
<xsl:call-template name="makeRef">
<xsl:with-param name="inString"
select="substring-after($inString, '/')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of
select="substring-before($inString,'|')"/>[(_at_)title='<xsl:value-of
select="substring-after($inString, '|')"/>']
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Here's the output from Saxon 8 (with a little hand formatting for clarity
and brevity):
<html>
<body>
<h1><a name="d1e3"></a>Chapter 1</h1>
<p>The remainder of this book contains the following material:</p>
<ul>
<li><a href="#d2">Chapter 2</a>
<ul>
<li><a href="#d3">Introduction</a></li>
</ul>
</li>
<li><a href="#d4">Chapter 3</a>
<ul>
<li><a href="#d5">Introduction</a></li>
</ul>
</li>
</ul>
<h1><a name="d1e36"></a>Chapter 2</h1>
<h3><a name="d1e38">Introduction</a></h3>
<h1><a name="d1e41"></a>Chapter 3</h1>
<h3><a name="d1e43">Introduction</a></h3>
</body>
</html>
I gather that generate-id is treating the path I build as a string, so
it's not working.
My concern is not how to get generate-id to accept a string as a path
(though I would be curious about that). My concern is to be able to create
cross-references to identical elements (that do have different parent
elements). I have total control over the XML input and the XSL stylesheet,
so I am open to ANY idea that will get the job done.
Thanks very much.
Jay Bryant
Bryant Communication Services