Re: [xsl] XSLT 1.0: Grouping Adjacent Elements in Embedded Lists

Subject: Re: [xsl] XSLT 1.0: Grouping Adjacent Elements in Embedded Lists
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Thu, 04 Nov 2004 18:30:26 -0500
Joe,

I haven't tested this, but I think you're almost there.

At 03:21 PM 11/4/2004, you wrote:
I'm pretty sure I have to edit this part to account for the case when preceding-sibling is <EM_OL_LI>

        <xsl:if test="not(preceding-sibling::*[1][self::OL_LI])">
              <p>
                 <ol>
                    <xsl:apply-templates select="." mode="li"/>
                 </ol>
              </p>
           </xsl:if>

But my attempts have been fruitless.

I think you're correct, though. Or to refine slightly: it's not the special case of an OL_LI that has a preceding EM_OL_LI, but rather that the *first* OL_LI in the group is the special case.


That is, you want this kick-off (the creation of the p and ol wrappers and the initiation of the "walk" you perform to occur for the first OL_LI, but no others.

This would be a simple matter of changing your test to:

<xsl:if test="not(preceding-sibling::OL_LI)">
  <p>
    <ol>
      <xsl:apply-templates select="." mode="li"/>
    </ol>
  </p>
</xsl:if>

which is to say "if there's no OL_LI before this one, start my list" instead of "if the immediately preceding sibling is not an OL_LI, start my list".

Now, if your lists aren't wrapped at all, but are completely flat and appear mixed in with other elements (such as paragraphs or whatever) you might need a test that says "if the immediately preceding sibling is not an OL_LI or an EM_OL_LI, start my list". That would be

<xsl:if test="not(preceding-sibling::*[1][self::OL_LI|self::EM_OL_LI])">
  <p>
    <ol>
      <xsl:apply-templates select="." mode="li"/>
    </ol>
  </p>
</xsl:if>

And if someone could explain to me the difference between [self::OL_LI] and [OL_LI] that would be an added educational bonus. Thanks!

"OL_LI" in XPath is short for "child::OL_LI", so the difference here is the same as the difference between [self::OL_LI] (the predicate tests true for context nodes that are OL_LI elements) and [child::OL_LI] (the predicate tests true for context nodes that have OL_LI children).


The expression "*[self::X|self::Y]" returns a child element ("*" being short for "child::*") that is either an X or a Y (the predicate returns a union of the set of X elements that are the context node and the set of Y elements that are the context node -- i.e. the context node if it's an X or a Y, nothing if it's something else).

I hope this helps,
Wendell


====================================================================== Wendell Piez mailto:wapiez@xxxxxxxxxxxxxxxx Mulberry Technologies, Inc. http://www.mulberrytech.com 17 West Jefferson Street Direct Phone: 301/315-9635 Suite 207 Phone: 301/315-9631 Rockville, MD 20850 Fax: 301/315-8285 ---------------------------------------------------------------------- Mulberry Technologies: A Consultancy Specializing in SGML and XML ======================================================================

Current Thread