bitmask
bitmask

Reputation: 34636

Can you use XSL to transform line-separated lists into proper xhtml lists?

XSL is meant to transform XML to XML, but can you transform a file like

line1
line 2 -- foo
line 3

into

<ol>
<li>line1</li>
<li>line 2 -- foo</li>
<li>line 3</li>
</ol>

using XSLT only?

Upvotes: 2

Views: 97

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243529

This is straightforward in XSLT 2.0 and also not difficult in XSLT 1.0:

I. XSLT 1.0 solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <ol>
    <xsl:apply-templates/>
  </ol>
 </xsl:template>

 <xsl:template match="text()" name="linesToLi">
  <xsl:param name="pText" select="."/>

  <xsl:if test="string-length($pText) > 0">
      <xsl:variable name="vthisLine" select=
      "substring-before(concat($pText, '&#xA;'), '&#xA;')"/>

      <li><xsl:value-of select="$vthisLine"/></li>

      <xsl:call-template name="linesToLi">
       <xsl:with-param name="pText" select="substring-after($pText, '&#xA;')"/>
      </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document (the provided text, wrapped into a single top element to be made a well-formed XML document):

<t>line1
line 2 -- foo
line 3</t>

the wanted, correct result is produced:

<ol>
   <li>line1</li>
   <li>line 2 -- foo</li>
   <li>line 3</li>
</ol>

II. XSLT 2.0 solution:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vText" as="xs:string">
 line1
 line 2 -- foo
 line 3
 </xsl:variable>

 <xsl:template match="/">
  <ol>
    <xsl:for-each select=
       "tokenize($vText, '\r?\n')[normalize-space()]">
      <li><xsl:sequence select="."/></li>
    </xsl:for-each>
  </ol>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on any XML document (not used), the wanted, correct result is produced:

<ol>
    <li> line1</li>
    <li> line 2 -- foo</li>
    <li> line 3</li>
</ol>

Do note:

Using the XSLT 2.0 function unparsed-text() we can process any text file as a string and split it into lines using the above code.

More precisely, we will use something like this:

tokenize(unparsed-text($vSomeUrl), '\r?\n')[normalize-space()]

Upvotes: 3

Lucero
Lucero

Reputation: 60236

Unfortunately XSLT 1 has no efficient string handling and parsing facilities, so that it's not really suitable for tasks like this (even though it is possible).

With XSLT 2 this has changed. See for instance this paper on XSLT 2 text parsing.

Upvotes: 1

Related Questions