[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: generating a repeatable unique id

Subject: Re: generating a repeatable unique id
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Mon, 30 Jul 2001 17:14:22 +0100
xpath unique id
Hi Sebastian,

>> Of course you should use different separators to make it a valid ID
>> so that it can be an HTML anchor, e.g.:
>>
>>   chapter1.section2.div3
>
> thats fine, I can see that nicely. I still have the problem, though,
> of turning that back into the value for a <xsl:apply-templates>
> select attribute, don't I, when I reenter the document?

Oh, it depends on how you're doing the linking. I was imagining that
you were creating something an index.html document with the links in,
containing things like:

  <p><a href="doc.html#chapter1.section2.div3">...</a></p>

And then had a doc.html document with the anchors for the links,
containing things like:

  <h3 id="chapter1.section2.div3">...</h3>

In other words, that you were creating the links by having the IDs
that you refer to in index.html be the same as the IDs that you use
within doc.html. You can make sure that they're the same by having a
module containing a moded template like:

<xsl:template match="*" mode="id">
  <xsl:for-each select="ancestor-or-self::*">...</xsl:for-each>
</xsl:template>

Import that module into the stylesheet for index.html and for
doc.html. In the stylesheet generating index.html have:

  <a>
    <xsl:attribute name="href">
      <xsl:text>doc.html#</xsl:text>
      <xsl:apply-templates select="." mode="id" />
    </xsl:attribute>
    ...
  </a>

In the stylesheet generating doc.html, have:

  <h3>
    <xsl:attribute name="id">
      <xsl:apply-templates select="." mode="id" />
    </xsl:attribute>
    ...
  </h3>

i.e. the same ID value is used in both because you use the same
template to generate them both.

But perhaps you were meaning that you wanted to only display the part
of the document that you were linking to? Of course in the future all
you'd need to do is generate:

<p><a href="doc.xml#xpointer(/chapter[1]/section[2]/div[3])">...</a></p>

But for now I guess you would generate a link that looked something
like:

<p><a href="doc.xml?xpath=/chapter[1]/section[2]/div[3]">...</a></p>

With some magic on the server end, you'd get an $xpath parameter in
your stylesheet.

You could step through the $xpath parameter to locate and apply
templates to the relevant part of the document, something like:

<xsl:template match="*" mode="xpath">
  <xsl:param name="xpath" />
  <xsl:choose>
    <!-- if there is a path -->
    <xsl:when test="$xpath">
      <!-- step is the part before the '/' (if there is one) -->
      <xsl:variable name="step">
        <xsl:choose>
          <xsl:when test="contains($xpath, '/')">
            <xsl:value-of select="substring-before($xpath, '/')" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$xpath" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <!-- the child's name is the part before the '[' -->
      <xsl:variable name="childName"
                    select="substring-before($step, '[')" />
      <!-- and its index is the part between the []s -->
      <xsl:variable name="childIndex"
                    select="substring-before(
                              substring-after($step, '['), ']'))" />
      <!-- so apply templates to that child, passing in the $xpath
           left after the first step -->
      <xsl:apply-templates select="*[name() = $childName]
                                    [number($childIndex)]">
         <xsl:with-param name="xpath"
                         select="substring-after($xpath, '/')" />
      </xsl:apply-templates>
    </xsl:when>
    <!-- if there's no path left, then this is the element we want -->
    <xsl:otherwise>
      <!-- apply templates to it (or do something else) -->
      <xsl:apply-templates select="." />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

You could kick it off with something like:

<xsl:template match="/">
  <xsl:apply-templates select="*" mode="xpath">
    <xsl:with-param name="xpath"
                    select="substring-after($xpath, '/')" />
  </xsl:apply-templates>
</xsl:template>

Your other option, the one that you were referring to, would be to
generate an XSLT stylesheet that used the XPath. The generator
stylesheet would contain something like:

<xsl:template match="/">
  <oxsl:template match="/">
    <oxsl:apply-templates select="{$xpath}" />
  </oxsl:template>
</xsl:template>

And you might want to pass the URL for the document in there as well,
to make things easier.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.