RE: [xsl] Handling Mixed Child Elements and Text() Nodes

Subject: RE: [xsl] Handling Mixed Child Elements and Text() Nodes
From: Americo Albuquerque <melinor@xxxxxxxx>
Date: Wed, 1 Oct 2003 01:55:19 +0100
Hi

Check stylesheet for comments
This is basically your stylesheet with some tweaks

Input:
<page>
<body>
<text>
<subhead>Linked Text</subhead>

<link url="a">A</link>

<link url="b">B</link>

<link url="c">C</link>

<link url="d">D</link> (AKA X)

<link url="e">E</link>

<subhead>Unlinked Text</subhead>

F

G

H

I

J

</text>
</body>
</page>

Output:



<div class="body_subhead">Linked Text</div>

<div class="body"><a href="a" class="body">A</a></div>

<div class="body"><a href="b" class="body">B</a></div>

<div class="body"><a href="c" class="body">C</a></div>

<div class="body"><a href="d" class="body">D</a> (AKA X)</div>

<div class="body"><a href="e" class="body">E</a></div>

<div class="body_subhead">Unlinked Text</div>

<div class="body">F</div>

<div class="body">G</div>

<div class="body">H</div>

<div class="body">I</div>

<div class="body">J</div>



Regards,
Americo Albuquerque

Stylesheet:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:key match="text/node()" name="x"
use="generate-id((..|preceding-sibling::text()[contains(.,'&#10;')][1])[
last()])"/>
  <!-- removed the 'y' key -->
  <xsl:template match="link">
    <xsl:param name="linkClass"/>
    <xsl:param name="divClass"/>
    <a href="{@url}">
      <xsl:attribute name="class">
        <xsl:value-of select="$linkClass"/>
      </xsl:attribute>
      <xsl:apply-templates>
        <xsl:with-param name="linkClass" select="$linkClass"/>
      </xsl:apply-templates>
    </a>
  </xsl:template>
  <xsl:template match="subhead">
    <xsl:param name="divClass"/>
    <!-- removed div element -->
    <xsl:attribute name="class">
      <xsl:value-of select="$divClass"/>_subhead</xsl:attribute>
    <xsl:value-of select="."/>
  </xsl:template>
  <xsl:template match="text">
    <xsl:param name="divClass"/>
    <xsl:param name="linkClass"/>
    <xsl:for-each select=".|text()[contains(.,'&#10;')]">
      <xsl:call-template name="d1">
        <xsl:with-param name="s"
select="substring-after(self::text(),'&#10;')"/>
        <xsl:with-param name="divClass" select="$divClass"/>
        <xsl:with-param name="linkClass" select="$linkClass"/>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name="d1">
    <xsl:param name="s"/>
    <xsl:param name="divClass"/>
    <xsl:param name="linkClass"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:choose>
      <xsl:when test="contains($s,'&#10;')">
        <!-- wrap the div element with a xsl:if -->
        <xsl:if test="substring-before($s,'&#10;')">
          <div>
            <xsl:attribute name="class">
              <xsl:value-of select="$divClass"/>
            </xsl:attribute>
            <xsl:value-of select="substring-before($s,'&#10;')"/>
          </div>
        </xsl:if>
        <xsl:call-template name="d1">
          <xsl:with-param name="s"
select="substring-after($s,'&#10;')"/>
          <xsl:with-param name="linkClass" select="$linkClass"/>
          <xsl:with-param name="divClass" select="$divClass"/>
        </xsl:call-template>
      </xsl:when>
      <!-- add xsl:when clause -->
      <xsl:when
test="not(concat($s,key('x',generate-id(.))[position()&lt;last()],substr
ing-before(key('x',generate-id(.))[last()],'&#10;')))"/>
      <xsl:otherwise>
        <div>
          <xsl:attribute name="class">
            <xsl:value-of select="$divClass"/>
          </xsl:attribute>
          <xsl:value-of select="$s"/>
          <xsl:apply-templates
select="key('x',generate-id(.))[position()&lt;last()]">
            <xsl:with-param name="linkClass" select="$linkClass"/>
            <xsl:with-param name="divClass" select="$divClass"/>
          </xsl:apply-templates>
          <xsl:value-of
select="substring-before(key('x',generate-id(.))[last()],'&#10;')"/>
          <xsl:if test="position() = last()">
            <xsl:apply-templates
select="key('x',generate-id(.))[last()]">
              <xsl:with-param name="linkClass" select="$linkClass"/>
              <xsl:with-param name="divClass" select="$divClass"/>
            </xsl:apply-templates>
          </xsl:if>
        </div>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <!-- xsl:for-each was child of xsl:stylesheet, this is an error, so
i've change it to xsl:template -->
  <xsl:template match="/page/body">
    <xsl:apply-templates>
      <xsl:with-param name="textNode"
select="key('x',generate-id(.))[position()&lt;last()]"/>
      <xsl:with-param name="divClass" select="'body'"/>
      <xsl:with-param name="linkClass" select="'body'"/>
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>


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


Current Thread