←back to thread

418 points akagusu | 7 comments | | HN request time: 0.684s | source | bottom
Show context
dfabulich ◴[] No.45955306[source]
In part 1 of this article, the author wrote, "XSLT is an essential companion to RSS, as it allows the feed itself to be perused in the browser"

Actually, you can make an RSS feed user-browsable by using JavaScript instead. You can even run XSLT in JavaScript, which is what Google's polyfill does.

I've written thousands of lines of XSLT. JavaScript is better than XSLT in every way, which is why JavaScript has thrived and XSLT has dwindled.

This is why XSLT has got to go: https://www.offensivecon.org/speakers/2025/ivan-fratric.html

replies(7): >>45955537 #>>45955587 #>>45955938 #>>45955985 #>>45956639 #>>45956745 #>>45958606 #
ndriscoll ◴[] No.45955537[source]
> JavaScript is better than XSLT in every way

Obviously not in every way. XSLT is declarative and builds pretty naturally off of HTML for someone who doesn't know any programming languages. It gives a very low-effort but fairly high power (especially considering its neglect) on-ramp to templated web pages with no build steps or special server software (e.g. PHP, Ruby) that you need to maintain. It's an extremely natural fit if you want to add new custom HTML elements. You link a template just like you link a CSS file to reuse styles. Obvious.

The equivalent Javascript functionality's documentation[0] starts going on about classes and callbacks and shadow DOM, which is by contrast not at all approachable for someone who just wants to make a web page. Obviously Javascript is necessary if you want to make a web application, but those are incredibly rare, and it's expected that you'll need a programmer if you need to make an application.

Part of the death of the open web is that the companies that control the web's direction don't care about empowering individuals to do simple things in a simple way without their involvement. Since there's no simple, open way to make your own page that people can subscribe to (RSS support having been removed from browsers instead of expanded upon for e.g. a live home page), everyone needs to be on e.g. Facebook.

It's the same with how they make it a pain to just copy your music onto your phone or backup your photos off of it, but instead you can pay them monthly for streaming and cloud storage.

[0] https://developer.mozilla.org/en-US/docs/Web/API/Web_compone...

replies(5): >>45955706 #>>45955862 #>>45955946 #>>45956123 #>>45957628 #
ErroneousBosh ◴[] No.45955946[source]
> not at all approachable for someone who just wants to make a web page

If someone wants to make a web page they need to learn HTML and CSS.

Why would adding a fragile and little-used technology like XSLT help?

replies(2): >>45957790 #>>45958199 #
basscomm ◴[] No.45958199[source]
> Why would adding a fragile and little-used technology like XSLT help?

A few years ago I bought a bunch of Skylanders for practically nothing when the toys to life fad faded away. To keep track of everything I made a quick and dirty XSLT script that sorted and organized the list of figures and formatted each one based on their 'element'. That would have been murderous to do in plain HTML and CSS: https://wyrm.org/inventory/skylanders.xml

replies(1): >>45962060 #
1. dfabulich ◴[] No.45962060[source]
It would have been murderous with just CSS, but it would have been trivial to do with JS, much easier than the hundreds of lines of XSL you wrote. https://wyrm.org/inventory/skylanders.xsl
replies(1): >>45965154 #
2. basscomm ◴[] No.45965154[source]
> but it would have been trivial to do with JS

Maybe! How much Javascript would I have to learn before I could come up with a 'trivial' solution?

> the hundreds of lines of XSL you wrote.

Those hundreds of lines are the same copy/pasted if statement with 5 different conditions. For each game, I create a table by: alphabetizing the XML > going through the list searching for figures that match the game > each time I find one go through the color list to find the color to use for the table row. There are 10 color choices per game, which means that I repeated a 10-choice if statement 5 times.

There's nothing difficult here, it's just verbose.

replies(2): >>45969849 #>>45979231 #
3. ndriscoll ◴[] No.45969849[source]
Aside: you could factor that out by making an <xsl:template match="figure"> that does the choose on element, then your repeated code can just expand that template. The immense power in XSLT comes from xpath to make it easy to match on things like "all figures that contain a <name series=1/>":

  <table>
  <tr><th>Skylanders figure</th><th>Note</th></tr>
  <xsl:apply-templates select="skylanders/figure[name/@series=1]">
  <xsl:sort select="name"/>
  </xsl:apply-templates>
  </table>
If you further refactor the XML, you could do e.g.

  <skylanders>
    <figure name="Hijinx" element="undead" series="3" note=""/>
    <figure name="Eye Small" element="undead" series="3" note=""/>
    <figure name="Air Screamer" element="air" series="3" note="Storm Warning"/>
     ...
    <figure name="Blast Zone" element="fire" series="2" note="Bottom only"/>

    <series name="Skylanders Giants" id="1"/>
    <series name="Skylanders SWAP Force" id="2"/>
    <series name="Skylanders Trap Team" id="3"/>
    <series name="Skylanders Superchargers" id="4"/>
    <series name="Skylanders Imaginators" id="5"/>
  </skylanders>
And then you can entirely eliminate the verbosity in your XSL. The templates become:

  <xsl:template match="series">
  <h2><xsl:value-of select="@name"/></h2>
  <table>
    <tr><th>Skylanders figure</th><th>Note</th></tr>
    <xsl:apply-templates select="/skylanders/figure[@series=current()/@id]"><xsl:sort select="name"/></xsl:apply-templates>
  </table>
  </xsl:template>

  <xsl:template match="figure">
  <tr class="element-{ @element }">
    <td><xsl:value-of select="@name" /></td>
    <td><xsl:value-of select="@note" /></td>
  </tr>
  </xsl:template>
...

  <style>
  .element-air      td { background: skyblue;      color: black; }
  .element-dark     td { background: dimgrey;      color: black; }
  .element-earth    td { background: saddlebrown;  color: white; }
  .element-fire     td { background: firebrick;    color: white; }
  .element-life     td { background: darkgreen;    color: white; }
  .element-light    td { background: ivory;        color: black; }
  .element-magic    td { background: purple;       color: white; }
  .element-tech     td { background: orangered;    color: white; }
  .element-undead   td { background: midnightblue; color: white; }
  .element-water    td { background: blue;         color: white; }
  .element-none     td { background: black;        color: white; }
  </style>
...

Then in your body area:

  <xsl:apply-templates select="skylanders/series"><xsl:sort select="id"/></xsl:apply-templates>


You can actually use XSL to do the XML refactor too! ChatGPT happily obliges a template to do so:

  <?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes" />

  <xsl:template match="/skylanders">
    <skylanders>
      <xsl:apply-templates select="figure"/>
    </skylanders>
  </xsl:template>

  <xsl:template match="figure">
    <figure>
      <xsl:attribute name="name">
        <xsl:value-of select="name"/>
      </xsl:attribute>
      <xsl:attribute name="element">
        <xsl:call-template name="convert-element">
          <xsl:with-param name="code" select="name/@element"/>
        </xsl:call-template>
      </xsl:attribute>

      <xsl:attribute name="series">
        <xsl:value-of select="name/@series"/>
      </xsl:attribute>
      <xsl:attribute name="note">
        <xsl:value-of select="normalize-space(note)"/>
      </xsl:attribute>
    </figure>
  </xsl:template>
  <xsl:template name="convert-element">
    <xsl:param name="code"/>
    <xsl:choose>
      <xsl:when test="$code = 0">air</xsl:when>
      <xsl:when test="$code = 1">dark</xsl:when>
      <xsl:when test="$code = 2">earth</xsl:when>
      <xsl:when test="$code = 3">fire</xsl:when>
      <xsl:when test="$code = 4">life</xsl:when>
      <xsl:when test="$code = 5">light</xsl:when>
      <xsl:when test="$code = 6">magic</xsl:when>
      <xsl:when test="$code = 7">tech</xsl:when>
      <xsl:when test="$code = 8">undead</xsl:when>
      <xsl:when test="$code = 9">water</xsl:when>
      <xsl:when test="$code = 10">none</xsl:when>
      <xsl:otherwise>unknown</xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  </xsl:stylesheet>

Then `xsltproc refactor.xsl skylanders.xml > skylanders-refactored.xml`

As I've said elsewhere, I like XSL for its beginner-approachability, so not doing a bunch of factoring is fine, but I also like it for its power: such factoring into simple templates is possible once you wrap your head around the idea (as with CSS). Using for-each or choose should be a sign you're doing it wrong. Ideally if you did your data model well, you just do simple template expansions everywhere.

replies(1): >>45974884 #
4. basscomm ◴[] No.45974884{3}[source]
> Using for-each or choose should be a sign you're doing it wrong.

I wouldn't say that I did it wrong, I just didn't do it efficiently. And I knew that at the time.

I appreciate the work, but I've said it elsewhere: I'm not a programmer. This was something I spent a couple of afternoons on five years ago and never looked at again after getting the results I wanted.

replies(1): >>45975319 #
5. ndriscoll ◴[] No.45975319{4}[source]
Sorry, I communicated poorly there, and was kind of replying more to the other commenter. I actually meant to reinforce your point that you didn't need some complex hundreds-of-lines-of-code template (and that what you had wasn't complex), and if you wanted to put in that effort, you could've condensed it here too to just 2 small templates.

The thing about doing it wrong was meant as a reply to the comment upthread about for-each etc. being necessary. For something like you have, they're absolutely not. It's fine if that was the easiest way for you to do it though. My whole point was that I've always seen XSLT as much more of an approachable, enabling technology than modern JS approaches.

6. ErroneousBosh ◴[] No.45979231[source]
> Maybe! How much Javascript would I have to learn before I could come up with a 'trivial' solution?

Less than the amount of XSL you'd need.

> Those hundreds of lines are the same copy/pasted if statement with 5 different conditions.

With a programming language, you could have used loops.

replies(1): >>45979755 #
7. ndriscoll ◴[] No.45979755{3}[source]
What an odd comment to have as a sibling to mine from yesterday showing how to do it with two small templates in xsl (after a minor tweak to the xml):

  <xsl:template match="series">
  <h2><xsl:value-of select="@name"/></h2>
  <table>
    <tr><th>Skylanders figure</th><th>Note</th></tr>
    <xsl:apply-templates select="/skylanders/figure[@series=current()/@id]"><xsl:sort select="name"/></xsl:apply-templates>
  </table>
  </xsl:template>

  <xsl:template match="figure">
  <tr class="element-{ @element }">
    <td><xsl:value-of select="@name" /></td>
    <td><xsl:value-of select="@note" /></td>
  </tr>
  </xsl:template>
No explicit loops necessary.