[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] XSL pattern needed for begin/end elements


Subject: Re: [xsl] XSL pattern needed for begin/end elements
From: "M. David Peterson" <m.david@xxxxxxxxxx>
Date: Wed, 07 Jul 2004 16:33:13 -0600

Tracy,

I am soooo sorry this took so long but my day has been bouncing back and forth and every time I would get a chance to sit down and write this something else would come along... Anyway, I finally got ten minutes to get this written out real quick... The key is to use generate-id() against hyperlink_end in the first position that follows the current hyperlink_begin. By creating a variable that holds the value of the generate-id() process we can then check to make sure that as we are processing the run_text elements that they dont have a preceding-sibling that generates the same id that is stored in our variable. So this:

<xsl:template match="/">
  <xsl:apply-templates select="doc/hyperlink_begin"/>
</xsl:template>

<xsl:template match="hyperlink_begin">
<xsl:variable name="count" select="generate-id(following-sibling::hyperlink_end[1])"/>
<cod>
  <Hyperlink>
    <xsl:attribute name="xLink:href"><xsl:value-of select="concat(locator_url/@protocol, '://', locator_url/@host_name)"/></xsl:attribute>
    <xsl:apply-templates select="following-sibling::text_run[not(generate-id(preceding-sibling::hyperlink_end) = $count)]"/>
  </Hyperlink>
</cod>
</xsl:template>

<xsl:template match="text_run[@emphasis]">
  <b><xsl:value-of select="."/></b>
</xsl:template>

<xsl:template match="text_run">
  <xsl:value-of select="."/>
</xsl:template>

Will produce the output you want by ensuring that the only text_run elements that are processed are sandwiched between the current hyperlink_begin and the hyperlink_end in the first position after the current context. Does that make sense?

So this XML:

  <doc>
    <hyperlink_begin id="111" end="222">
      <locator_url protocol="http" host_name="www.sf.net"/>
    </hyperlink_begin>
    <text_run>Click</text_run>
     <text_run emphasis="bold">here One.</text_run>
    <hyperlink_end id="222" begin="111"/>
    <hyperlink_begin id="111" end="222">
      <locator_url protocol="http" host_name="www.sf.net"/>
    </hyperlink_begin>
    <text_run>Click</text_run>
     <text_run emphasis="bold">here Two.</text_run>
    <hyperlink_end id="222" begin="111"/>
  </doc>

Gets processed and output as such:

<?xml version="1.0" encoding="UTF-8"?>
<cod>
  <Hyperlink xLink:href="http://www.sf.net">Click<b>here One.</b>
  </Hyperlink>
</cod>
<cod>
  <Hyperlink xLink:href="http://www.sf.net">Click<b>here Two.</b>
  </Hyperlink>
</cod>

And im pretty sure thats what you wanted?

Hope this helped!

Regards,

<M:D/>

Tracy Atteberry wrote:
Sorry about that.  Looks like my client was inserting '3D's after every
'='.  Let's try again...

---------------
Hi all,

I'm looking for an XSL pattern to solve the problem of going from XML
that has separate begin and end elements to one that does not.

Please, please note that I do not control either the source or target
XML formats.  If I did, this would be much easier.

Source XML snip:

<doc>
  <hyperlink_begin id="111" end="222">
    <locator_url protocol="http" host_name="www.sf.net"/>
  </hyperlink_begin>
  <text_run>Click</text_run>
  <text_run emphasis="bold">here.</text_run>
  <hyperlink_end id="222" begin="111"/>
</doc>

Target XML example:

<cod>
  <HyperLink xlink:href="http://www.sf.net">
    Click <b>here.</b>
  </HyperLink>
</cod>

In my case I can assume that associated begin and end hyperlink tags
will occur as siblings -- though generally this is not the case and in
fact, this is the reason the begin and end tags are unique elements.

I have a template that /almost/ works so feel free to let me know why it
fails OR suggest a completely different solution.

Current XSL template snip:

<xsl:template match="//hyperlink_begin">
    <xsl:variable name="linkUrl">
        <xsl:value-of select="locator_url/@protocol"/>
        <xsl:text>://</xsl:text>
        <xsl:value-of select="locator_url/@host_name"/>
    </xsl:variable>
    <xsl:variable name="endID" select="@end"/>
    <xsl:element name="HyperLink">
        <xsl:attribute name="xlink:href"><xsl:value-of
select="$linkUrl"/></xsl:attribute>
        <xsl:apply-templates select="(following-sibling::*) except
(following-sibling::hyperlink_end[@id=$endID]/following-sibling::*)"/>
    </xsl:element>
</xsl:template>

This produces the correct hyperlink but the template for text_run
elements gets called twice this way -- once inside the hyperlink, then
again as templates continue to be applied.

Any help would be greatly appreciated. Thanks!

Tracy Atteberry

PS. I'm using Saxon 8



--+------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe@xxxxxxxxxxxxxxxxxxxxxx>
--+--



Current Thread
Keywords