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

Re: paras with nested block-level elements to XHTML mi

Subject: Re: paras with nested block-level elements to XHTML mix of <p>s and flattened block-level elements
From: Syd Bauman <Syd_Bauman@xxxxxxxxx>
Date: Fri, 1 Aug 2008 15:28:51 -0400
Re:  paras with nested block-level elements to XHTML mi
> My question concerns X/HTML as the transformation target, where "p"
> is the lowest level block-level element, which admits no other
> block-level element(s) as content, but the source is a model (like
> DocBook, TEI, etc.) which allows (and has) a variety of block level
> content in paragraphs.

The following snippets of XSLT 2.0 are what I've been using to
transform <tei:p> elements that contain <tei:list> or <tei:eg> into
XHTML. I do not claim (at all) that this is a good, let alone the
best way to do this, but rather only that it has been working for me.

---------
  <!--
    ** This section contains all the code for moving <list>s and <eg>s that
    ** are nested inside <p>s to being the middle siblings of two <p>s. I.e.:
    ** | <p>Blah-blah-01
    ** |   <eg>exampleA</eg>
    ** |   Blah-blah-02
    ** |   <eg>exampleB</eg>
    ** |   Blah-blah-03</p>
    ** should be transformed into
    ** | <p>Blah-blah-01</p>
    ** | <pre>exampleA</pre>
    ** | <p>Blah-blah-02</p>
    ** | <pre>exampleB</pre>
    ** | <p>Blah-blah-03</p>
    -->
  <xsl:template match="in:p">
    <!-- first handle content up to and including the last <eg> or <list> inside me -->
    <xsl:call-template name="eg-and-list-in-p"/>
    <!-- Note that if there is no <eg> or <list>, the above template did nothing. -->
    <!-- So now we still need to handle the content from the last <eg> or <list> -->
    <!-- (exclusive of it) to the end-of-me, and all my content if there was no -->
    <!-- <eg> or <list>. So the first step is to select all such nodes and tuck 'em -->
    <!-- in a variable. So this XPath selects all nodes that are not <eg> or <list> -->
    <!-- and do not have any <eg> or <list> following. Thus, if there is neither -->
    <!-- an <eg> nor a <list>, it selects all my child nodes. -->
    <xsl:variable name="end-content"
      select="node()[not(self::in:list or self::in:eg) and not(following-sibling::in:list or following-sibling::in:eg)]"/>
    <xsl:if test="$end-content">
      <xsl:element name="p">
        <xsl:apply-templates select="$end-content"/>
      </xsl:element>
    </xsl:if>
  </xsl:template>
  
  <xsl:template name="eg-and-list-in-p">
    <!-- for each of my (this <p>'s) children <eg> or <list> ... -->
    <xsl:for-each select="./in:eg|./in:list">
      <!-- remember the <eg> or <list> before me (now "me" = current <eg> or <list>) -->
      <xsl:variable name="before-me" select="preceding-sibling::node()[self::in:eg or self::in:list][1]"/>
      <!-- 
        ** The content we want is everthing between it (previous <eg> or
        ** <list>, whichever it was) and me (the current <eg> or <list>).
        ** However, don't ask me exactly how this predicate works. While
        ** I understand each little piece, I think, I don't get the big
        ** picture, and I don't understand the detail of why the equality
        ** test could ever fail. It is modified from the incomparable Jeni
        ** Tennison's post to XSL-List of 2001-01-19T15:49Z "How to
        ** transform <BR> to </P><P>"
        ** (http://xslt.com/html/xsl-list/2001-01/msg00927.xhtml),
        ** which I found via Dave Pawson's awesomely helpful FAQ at
        ** http://www.dpawson.co.uk/xsl/index.xhtml
      -->
      <xsl:variable name="content"
        select="preceding-sibling::node()
        [not($before-me) or
        generate-id(preceding-sibling::node()[self::in:eg or self::in:list][1]) =
        generate-id($before-me)]" />
      <!-- if there is any content ... -->
      <xsl:if test="$content">
        <!-- ... put it out in a <p> before we ... -->
        <xsl:element name="p">
          <xsl:apply-templates select="$content"/>
        </xsl:element>
      </xsl:if>
      <!-- ... put current node (and its children) into the output tree. -->
      <xsl:apply-templates select="."/>
    </xsl:for-each>
  </xsl:template>
---------

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-2007 All Rights Reserved.