Subject: Re: [xsl] 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 |
> 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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] paras with nested block-l, Wendell Piez | Thread | Re: [xsl] multiple values for the k, Mukul Gandhi |
Re: [xsl] paras with nested block-l, Wendell Piez | Date | Re: [xsl] multiple values for the k, Mukul Gandhi |
Month |