XSLT - gregorymorrison/euler1 GitHub Wiki

Introduced in 1997, XSLT (Extensible Stylesheet Language Transformations) is a language for processing XML and producing output. An XSLT template defines a transformation from an XML data into something else. The typical use case is to transform XML into HTML to create dynamic web pages. XSLT is itself an instance of XML - it's basically a program mutilated into encoded as a valid XML.

Processing happens by passing both an XML and an XSL into a black box XSLT processor, which results in output. Because of this nature, your entire program has to be written as one document, and there is no stepping through it. It either processes successfully and produces output, or it fails and produces an error message. This type of language is Declarative - instead of telling the computer how to perform computation, you tell it what needs to be done and leave the details to it. The closest well-known analog would have to be the database query language SQL.

XSLT was designed with a very limited scope - to transform an XML data file into a different format, typically HTML. Given this, it has severe limitations - forget any built-in capacity for GUI work, file handling, threading, networking, etc; it doesn't even have any concept of looping! Like I said, severe. That said, the language is Turing-complete, so we can bend it to our will if we try really hard. For example, looping can be accomplished with recursion, as I'll illustrate shortly.

So, what's XSLT like to work with? Well, like its big brother XML, it's horribly verbose. And debugging is done with print statements. There's a lot to not like, but it does get the job done.

However, there's also a lot to like. For example. XSL can easily be used for metaprogramming. Since XSL can produce any document type, it can be used to produce XSL, which can then be fed back into the XSLT processor to produce, well, other stuff. Yay, meta recursion! It can theoretically emit any source or even object code which can then be processed. Have fun, but if you do this heavy metaprogramming, expect to be kicked in the frank-and-beans by your teammates... Here's a version of Euler1 in XSLT, which took me a couple of hours to write:

<?xml version="1.0" encoding="utf-8" ?>
<!-- Euler1 in XSLT -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:template name="euler1">
    <!-- define parameters with default values using the select keyword -->
    <xsl:param name="startAt" select="1"/>
    <xsl:param name="endAt" />
    <xsl:param name="result" select="0"/>

    <xsl:choose>
      <xsl:when test="$startAt &lt; $endAt">

        <!-- call euler1 recursively -->
        <xsl:choose>
          <xsl:when test="$startAt mod 3 = 0 or $startAt mod 5 = 0">
            <xsl:call-template name="euler1">
              <xsl:with-param name="startAt" select="$startAt + 1"/>
              <xsl:with-param name="endAt" select="$endAt"/>
              <!-- either pass in result + startAt -->
              <xsl:with-param name="result" select="$result + $startAt"/>
            </xsl:call-template>
          </xsl:when>

          <xsl:otherwise>
            <xsl:call-template name="euler1">
              <xsl:with-param name="startAt" select="$startAt + 1"/>
              <xsl:with-param name="endAt" select="$endAt"/>
              <!-- or pass in result -->
              <xsl:with-param name="result" select="$result"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>

      <xsl:otherwise>
        <!-- create return value -->
        <xsl:value-of select="$result"/>
      </xsl:otherwise>
    </xsl:choose>

  </xsl:template>

  <!-- Main procedure -->
  <xsl:template match="/">

    <!-- define variable to capture return value -->
    <xsl:variable name="result">
      <xsl:call-template name="euler1">
        <xsl:with-param name="endAt">1000</xsl:with-param>
      </xsl:call-template>
    </xsl:variable>

    <!-- print solution -->
    <xsl:value-of select="$result"/>
  </xsl:template>

</xsl:stylesheet>

The value-of directive is used to output values, in our case to console output at line 56. So what about where we create the return value at line 39? We use the same directive to return a value from a function? I'm not an XSLT expert by any means, but it appears that our call of euler1 at line 50 captures the output and binds it to the variable result declared at line 49. If it didn't, then we should see output for each value-of  statement, and yet there is only one line of output. Apparently XSLT  is more complex than it at first appears. This language appears trivial, but its Turing-completeness puts a lot of subtlety under its hood. My version here is XSLT version 1.0; version 2.0 adds a lot of new tricks, such as support for functions with typed return values.

Now, XSLT requires an XML as input, so we need to make an empty XML:

<?xml version="1.0"?>
<node>
</node>

For this example, I used xsltproc. Yum-install, then invoke xsltproc with your XSL and dummy XML:

$ xsltproc euler1.xsl _.xml
<?xml version="1.0"?>
233168
$
⚠️ **GitHub.com Fallback** ⚠️