Reputation: 34636
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
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, '
'), '
')"/>
<li><xsl:value-of select="$vthisLine"/></li>
<xsl:call-template name="linesToLi">
<xsl:with-param name="pText" select="substring-after($pText, '
')"/>
</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
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