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

RE: [xsl] iterate through nodes and determine output by node type


Subject: RE: [xsl] iterate through nodes and determine output by node type
From: "Scott Trenda" <Scott.Trenda@xxxxxxxx>
Date: Mon, 1 Oct 2007 11:43:49 -0500

For reference, the list of HTML elements is here:
http://www.w3.org/TR/html401/index/elements.html

Not sure where you'll find whether each one is block or inline, but I'd
imagine it'd be in the CSS recommendation.

Just caught a typo - document('')/html:elements will never select
anything, so add a */ before html:elements. And in the stylesheet,
usually you'd define a top-level variable like:
<xsl:variable name="inline-names"
select="document('')/*/html:elements/inline/@name"/>
to make it easier on the eyes, but since variable references aren't
allowed in template match expressions, it wouldn't work just like that.
A key would probably make it easier, but you'll have to play around with
that.

~ Scott


-----Original Message-----
From: Mario Madunic [mailto:hajduk@xxxxxxxx]
Sent: Monday, October 01, 2007 11:36 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] iterate through nodes and determine output by node
type

Thanks Scott,

Would not have thought of this solution. I'll give it a try and post the
results.

Marijan (Mario) Madunic

Quoting Scott Trenda <Scott.Trenda@xxxxxxxx>:

> Since you're implying that any text _and_ HTML inline elements not
> surrounded in a block-level tag should be wrapped in a <p> tag, it
looks
> like you're going to have to define what should be considered
> block-level and what should be considered inline-level in your
> stylesheet. (Pain in the neck.)
>
> From there, you'll want something like the following, which looks for
> any run of the same type of node and wraps it in a parent element:
>
>
> <html:elements>
>   <inline name=""/> <!-- this will match text nodes; watch out for
> comments and whitespace nodes -->
>   <inline name="a"/>
>   <inline name="abbr"/>
>   <inline name="acronym"/>
>   <!-- ... -->
>   <inline name="strong"/>
>   <!-- ad nauseum... you'll have to fill in the rest here -->
> </html:elements>
>
> <!-- since HTML elements aren't case-sensitive,
>      you'll probably need to use translate(., 'ABC...', 'abc...')
>      for robustness here, eventually -->
> <xsl:template match="//body/node()[name() =
> document('')/*/html:elements/inline/@name]">
>   <xsl:if test="not(name(preceding-sibling::node()[1]) =
> document('')/*/html:elements/inline/@name)">
>     <p>
>       <xsl:apply-templates select="." mode="inline-run"/>
>     </p>
>   </xsl:if>
> </xsl:template>
>
> <xsl:template match="node()" mode="inline-run">
>   <xsl:copy-of select="."/>
>   <xsl:apply-templates select="following-sibling::node[1][name() =
> document('')/*/html:elements/inline/@name]" mode="inline-run"/>
> </xsl:template>
>
>
>
> The document('')/html:elements/inline/@name part is a mouthful, but it
> just happens that the test for the type of node you're looking for is
> irritating to write. In general, the test for the initial element in
the
> run, coupled with a modal template to copy and apply-templates to the
> next matching node in a row, will give you the grouped wrap you're
> looking for. (Reversing is easy in this scenario too, just swap the
> positions of <copy-of/> and <apply-templates/> in the modal template.)
>
>
> ~ Scott
>
> -----Original Message-----
> From: Mario Madunic [mailto:hajduk@xxxxxxxx]
> Sent: Monday, October 01, 2007 10:41 AM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] iterate through nodes and determine output by node type
>
> I'd like to test all child elements of a body tag and wrap any text
> nodes (that
> can contain child elements itself)in a p tag and <apply-templates />
to
> any
> element nodes.
>
> Using XSLT 1.1
>
> Sample input
>
> <body>
>   blah blah blah <strong>blah blah blah</strong>
>   <p>a paragraph...</p>
>   <p>a paragraph...</p>
>   <table>
>     <tr>
>       <td>content goes here</td>
>       <td>content goes here</td>
>     <tr>
>   </table>
> </body>
>
> sample output
>
> <body>
>   <p>blah blah blah <strong>blah blah blah</strong></p>
>   <p>a paragraph...</p>
>   <p>a paragraph...</p>
>   <table>
>     <tr>
>       <td>content goes here</td>
>       <td>content goes here</td>
>     <tr>
>   </table>
> </body>
>
> Sample code
>
> <xsl:template match="//body">
>   <body>
>     <xsl:for-each select="child::*">
>       <xsl:choose>
>         <xsl:when test="text()">
>           <p id="{generate-id()}"><xsl:apply-templates /></p>
>         </xsl:when>
>         <xsl:otherwise>
>           <xsl:apply-templates />
>         </xsl:otherwise>
>       </xsl:choose>
>     </xsl:for-each>
>   </body>
> </xsl:template>
>
> Thanks
>
> Marijan (Mario) Madunic


Current Thread
Keywords