2 Punkte von GN⁺ 2025-06-28 | 1 Kommentare | Auf WhatsApp teilen
  • XSLT kann wie ein clientseitiges Build-System im Webbrowser genutzt werden, um XML-Daten in HTML umzuwandeln und die Komplexität statischer Site-Generatoren zu reduzieren
  • Eine typische statische Website besteht aus Daten wie .json, .md oder .txt, einem Build-System wie Hugo, Next.js oder Astro und statisch ausgegebenem HTML; große Frameworks können jedoch selbst für einen einfachen Markdown-Blog übermäßig viel Komplexität erzeugen
  • Wer nur HTML und CSS verwenden möchte, muss Header und Footer über mehrere Seiten hinweg manuell kopieren; HTML Imports gibt es nicht, und Web Components haben die Einschränkung, dass sie eine JavaScript-Engine benötigen
  • Fügt man einem XML-Dokument <?xml-stylesheet type="text/xsl" href="blog.xsl"?> hinzu und schreibt XSLT-Templates, kann der Browser beim Besuch die HTML-Ausgabe erzeugen
  • Dieser Ansatz lässt sich ohne JavaScript als statische Dateien deployen, ist aber keine perfekte Lösung, die alles ersetzt, sondern eine weitere Option für den Werkzeugkasten der Webentwicklung

Komplexität beim Build statischer Websites

  • Der typische Ablauf beim Erstellen einer statischen Website gliedert sich in Daten, Build-System und statische HTML-Ausgabe
    • Daten werden in Dateien wie .json, .md oder .txt gespeichert
    • Beispiele für Build-Systeme sind Hugo, Next.js und Astro
    • Das Endergebnis ist statisches HTML
  • Selbst wenn man Frameworks weglassen und nur einfaches HTML und CSS verwenden möchte, müssen bei vielen Seiten gemeinsame Header und Footer immer wieder kopiert werden
  • Mögliche Alternativen haben jeweils Einschränkungen
    • HTML Imports existieren nicht
    • Web Components benötigen JavaScript und damit eine JavaScript-Engine

Die Idee, den Browser als Build-System zu nutzen

  • Webbrowser verstehen bereits verschiedene Formate wie text/html, text/markdown und application/xml
  • Wenn man den Browser als System nutzt, das aus Daten HTML erzeugt, kann man einen auf Webstandards basierenden Ablauf ohne separate Build-Tools schaffen
  • Beim Versuch, RSS-Feeds ansprechender darzustellen, zeigte sich, dass XSLT als Stylesheet für XML-Dokumente verwendet werden kann
  • XML sieht HTML ähnlich, ist aber ein Format zur Datenrepräsentation, das nicht nur auf Webdaten beschränkt ist; das lässt sich in der XML spec nachlesen

Umwandlung von XML in HTML

  • Ein XML-Dokument kann Daten wie Blogbeiträge enthalten
<?xml version="1.0"?>
<blog>
  <post id="42" publishedAt="2025-06-26">
    <title>Hello XSLT</title>
    <tags>…</tags>
  </post>
</blog>
  • Einem XML-Dokument kann eine Deklaration hinzugefügt werden, die ein XSL-Stylesheet verknüpft
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="blog.xsl"?>
<blog>
  <post id="42" publishedAt="2025-06-26">
    <title>Hello XSLT</title>
    <tags>…</tags>
  </post>
</blog>
  • Ein XSLT-Template nimmt XML-Eingaben entgegen und gibt eine HTML-Struktur aus
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">;
  <xsl:output method="html" indent="yes" />
  <xsl:template match="/">
    <html>
      <head> … </head>
      <body> … </body>
    </html>
  </xsl:template>
</xsl:stylesheet>
  • XSLT lässt sich als (XML) => HTML betrachten und bietet Build-System-Funktionen wie Schleifen, Variablen und Imports
  • Daten aus dem übergeordneten XML-Dokument können in XSLT übernommen und dynamisch ausgegeben werden
<head>
  <xsl:value-of select="title" /> | Blog
</head>

Ausführung und Deployment

  • Öffnet man eine XML-Datei im Browser, kann die XSLT-Transformation ausgeführt werden
open blog.xml -a Safari
  • Alle Webbrowser unterstützen die XSLT-Transformation beim Seitenaufruf und zeigen das daraus resultierende HTML an
  • Dieser Ansatz verhält sich wie ein clientseitiges Build-System, das auf dem Computer des Nutzers läuft
  • Statische Dateien lassen sich einfach deployen, und der Ansatz funktioniert ohne JavaScript

Grenzen und Einordnung

  • Blogdaten müssen nicht als JSON, sondern als XML gespeichert werden; XML sieht jedoch wie HTML aus, ist leicht zu parsen, flexibel und wird nativ im Web unterstützt
  • Der XSLT-Ansatz ist nicht perfekt und ersetzt nicht alles
  • Er wird zu einem weiteren Werkzeug, das sich unter Nutzung alter Webstandards, Spezifikationen und Browserfunktionen für die Erstellung einfacher statischer Websites einsetzen lässt

1 Kommentare

 
GN⁺ 2025-06-28
Meinungen auf Hacker News
  • Ich habe einmal in einem Unternehmen gearbeitet, das XSLT intensiv für XML-Templates nutzte; es war nicht gut, und wenn es möglich gewesen wäre, wären wir vermutlich migriert.
    Trotz neuer Standards dominiert XSLT 1.0 immer noch, und im Vergleich zu neueren Standards ist es eingeschränkt und seltsam.
    Performance-Probleme in XSLT-Templates zu lösen, kommt der Hölle ziemlich nahe. Es ist eine Turing-vollständige Sprache im funktionalen Stil, aber Performance ist stark abstrahiert; ein Template, das bei den meisten Dokumenten gut lief, konnte bei einer einzigen Tabelle mit 100 Zeilen explodieren. Es stellte sich heraus, dass das Template zur Tabellenverarbeitung O(N^2) oder schlimmer war, und dass XPath in jeder Zeile wiederum O(N) oder mehr sein konnte; eine klare Optimierungsmethode gab es auch nicht. Wenn ich mich richtig erinnere, dauerte die Verarbeitung eines Dokuments mit XSLT über 7 Minuten.
    JS hat sicher andere Probleme, aber ungelöste algorithmische Komplexität gehört nicht dazu.

    • XSLT/XPath hat sich seit XSLT 1.0 weiterentwickelt.
      Heute kann man die Verarbeitung mit Funktionen wie key (Index) deutlich beschleunigen, und gute XSLT-Implementierungen wie Saxon helfen auch klar bei der Performance.
      Wenn man XML in andere Formate umwandelt, ist XSLT ziemlich praktisch, weil man die Logik strukturieren kann.
    • Ich weiß nicht, wo „XSLT 1.0 dominiert immer noch“ gelten soll.
      2013 habe ich viel XSLT verwendet, und schon damals war 1.0 aus meiner Sicht völlig tot. Saxon war für XSLT 2 kostenlos und hervorragend.
      Wir haben sowohl riesige Dokumente als auch viele kleine Dokumente transformiert, hatten aber keinerlei Performance-Probleme.
    • XSLT ist nicht einfach. Als Analogie: Es ist wie Prolog auf Zauberpilzen, mit einer steilen Lernkurve.
      Wenn man es einmal beherrscht, gibt es einem die Befriedigung, als hätte man ein Sudoku gelöst; meistens reichen aber deutlich kleinere Werkzeuge, um das Ziel zu erreichen, weshalb es sich schwer als Standardansatz für Build oder Templates eignet.
      Außerdem ist XML auch nicht gerade ein Format, das alle mögen.
    • XSLT scheint in einer Zeit entstanden zu sein, in der es selbstverständlich war, lange XML-Quelldokumente zu verarbeiten; dass verschachtelte Schleifen explodieren, wirkt daher so offensichtlich, dass es seltsam ist.
    • Ich frage mich, ob ihr die kommerzielle Version von Saxon nutzt. Sie ist nicht teuer, und gemessen an unterstützten Funktionen und Performance halte ich sie für ihren Preis wert.
      Wenn ich mich richtig erinnere, hat sie auch ziemlich clevere Optimierungen vorgenommen.
  • Das ist vielleicht eine ziemlich gewagte Vermutung, aber in den 1990er- bis 2000er-Jahren waren Browser so unterschiedlich, dass man begann, JS zu verwenden, um dasselbe Verhalten herzustellen; eigentlich gebraucht hätte man gute CSS-Styles und konsistentes Verhalten.
    Mit der Zeit begannen Browser, sich ähnlicher zu verhalten, aber man hatte sich bereits an Frameworks gewöhnt, die Seiten in allen Browsern gleich aussehen ließen, und das Paradigma verschob sich hin zum Rendern von JSON-Daten.
    Mit dem heutigen Stand der Technik können servergenerierte altmodische Webseiten völlig problemlos bewältigt werden; sie haben einen kleineren Footprint, sind schneller und verbrauchen weniger Speicher.
    Bei einer kürzlichen Migration eines Legacy-Systems habe ich eine Struktur im Stil der 2000er gesehen: „eine Seite pro HTTP-Request“. Obwohl jede Aktion wie Hinzufügen oder Löschen ein Neuladen erforderte, war sie deutlich schneller als das React-System. Das Internet ist schneller geworden, der Speicher von Smartphones wird von JS-Frameworks verschwendet, und im Backend geht es weiterhin meist um CRUD, Pagination und Transaktionen.

    • AJAX und DOM-Aktualisierungen wurden nicht einfach eingeführt, um Dinge „schneller“ zu machen, sondern um das Paradigma von Websites/Webdokumenten, die Dokumente anzeigen, zu verändern.
      Bei einfachen Sites wie HN passt ein vollständiger Seiten-Reload gut, und es gibt viele Fälle, in denen eine einfache Website statt eines JS-Frameworks völlig ausreicht.
      Aber es stimmt nicht, dass alle zu vollständigen Seiten-Reloads zurückkehren können. Bei echten Webanwendungen gibt es Fälle, in denen ein kompletter Reload eine furchtbare User Experience wäre.
      Im Allgemeinen lassen sich Websites, Webdokumente und Webformulare auch mit vollständigen Reloads umsetzen, aber für Webanwendungen, die komplexe Dinge anzeigen und manipulieren müssen, passt das nicht.
    • Diese Zeitlinie scheint mir nicht zu stimmen. JS wurde anfangs eher für Interaktivität genutzt als zur Standardisierung von Verhalten; DHTML und später AJAX waren Beispiele dafür.
      Damals stützte man sich auf User-Agent-Erkennung und diverse Quirks, um Layouts hinzubekommen, und ich glaube auch nicht, dass JS leicht auf layoutrelevante Elemente zugreifen konnte.
      Auch CSS brachte nicht sofort Konsistenz. Selbst nachdem die Funktionen vorhanden waren, war es chaotisch; man staunte zwar über CSS Zen Garden, schrieb den tatsächlichen Code aber noch mit Tabellen.
      Ich weiß auch nicht, ob Frameworks wirklich großen Einfluss auf ein „konsistentes Aussehen“ hatten. Als man sich von jQuery entfernte, war CSS bereits für das Aussehen zuständig.
    • Mit einem .NET/Kestrel/SQLite-Stack kann man serverseitig gerenderte Antworten in etwa maximal 4 Millisekunden ausliefern. In Release-Builds liegt die durchschnittliche Antwortzeit im Bereich von einigen Hundert Mikrosekunden.
      Das gilt unter Bedingungen, bei denen pro Seite mehrere Queries abgesetzt werden und viele komplexe Joins genutzt werden, um antwortspezifische Formen nur für die View zu erzeugen. Wenn man die Daten vor der Interpolation in HTML-Strings in die passende Form bringt, hilft das in Grenzfällen wie Tabellen mit 100.000 Zeilen enorm bei der Performance.
      Meiner Erfahrung nach ist es umso besser, je näher HTML-Template-Engine und Datenbank beieinander liegen. Letztlich ist auch ein strukturierter DOM nur ein Byte-Stream, der an den Client geschickt werden muss.
      Ich glaube, es ist eine bedeutungslose, selbstzweckhafte Industrie entstanden, die über ausgefeilte AST-/Parser-Ansätze nachdenkt, wo ein StringBuilder und kluge SQL-Queries genügen würden. Die Gegenargumente liefen meist auf eine sicherheitswächterhafte Haltung hinaus, die davon ausgeht, dass Entwickler HTML-Escaping-Funktionen nicht richtig benutzen können.
    • Dass die heutige Technik servergenerierte altmodische Webseiten bewältigen kann, hat eine Ausnahme: Internetverbindungen mit hoher Latenz: https://news.ycombinator.com/item?id=44326816
  • Es ist schade, dass die Technik wegen der Aufgeblähtheit von Enterprise-XML in den 2000ern altbacken wirkt und alle zum „saubereren“ JSON geströmt sind.
    XSLT und XPath sind sehr ausgereift und haben viele Probleme, mit denen man in anderen Formaten immer noch zu kämpfen hat, längst gelöst.
    Ich habe auch gute Erinnerungen daran, früher PHP-Stream-Wrapper und XSLT-include missbraucht zu haben.
    Vielleicht ist es nur ein altes Vorurteil, aber den Browser das lokal verarbeiten zu lassen, macht mich immer noch etwas nervös. Früher war das nämlich ein Minenfeld der Kompatibilität.

    • Alt, aber bei JSON vermisse ich immer noch ein paar der „Basics“ von XML. Zunächst einmal gab es eine ordentliche Standardisierungsorganisation.
      Dinge wie Schemas waren auf XML-Seite viel besser definiert, und gefühlt hat JSON fast zehn Jahre gebraucht, um aufzuholen.
      Die letzte XML-Technik, mit der ich mich richtig beschäftigt habe, war EXI: ein Übertragungsformat, das XML-Dokumente in einen komprimierten binären Datenstrom verwandelt. Denn Datenstrukturen in ASCII umzuwandeln, zu komprimieren, per HTTP zu senden und dann wieder zurückzuwandeln, ist schon etwas absurd.
      Heute sind protobuf-artige Ansätze populärer, aber wenn XML geblieben wäre, hätte daraus eine Welt ineinandergreifender, kompatibler Standards werden können. Zwischen protobuf/gRPC und JSON-APIs gibt es dagegen eine harte Grenze – vielleicht ist das aber auch besser so.
    • XML ist in Ordnung. Es ist etwas geschwätzig, aber im Vergleich zu YAML mag ich seine Präzision und Ausdruckskraft.
      XPath ist auch nicht schlecht. Es ist schwer, sich die ganze Syntax zu merken, aber mit ein bisschen Ausprobieren kommt man meistens dorthin, wo man hinwill.
      XSLT ist komplett wahnsinniger Unsinn und sollte in Flammen aufgehen.
    • Das Spiel Rimworld speichert alle Konfigurationsdaten des Spiels in XML und nutzt XPath fürs Modding, und das ist wirklich großartig.
      Als Kombination, die relativ stabile lokale Änderungen an Daten ermöglicht, ist XML + XPath stark unterschätzt. Vielleicht wegen XMLs Ruf als „altmodisch“ sieht man das in anderen Spielen kaum, aber für diesen Zweck ist es ein sehr robustes System.
      https://rimworldwiki.com/wiki/Modding_Tutorials/PatchOperati...
    • XML war ursprünglich eine vereinfachte Teilmenge von SGML, gedacht dafür, Markup im Web zu übertragen und das Markup-Vokabular und die Fähigkeiten des Browsers weiterzuentwickeln.
      Als der Web-Hype aber größer wurde, bauten W3C und MS Dinge wie SOAP und WS-*, und es entstanden auch mehrere XML-basierte Programmiersprachen, darunter XSLT.
      Man sollte das den HN-Leuten nicht sagen, aber XSLT war ursprünglich Scheme, nur dass es unbedingt XML sein musste – dieselbe verrückte Zeit, in der JavaScript sich den Namen Java leihen musste.
    • XPath wäre schön gewesen, wenn man nicht jeden Teil jeder Abfrage pedantisch mit Namespaces hätte versehen müssen.
  • Heutzutage nutze ich XSLT, um Feeds hübsch zu machen.
    Zum Beispiel https://susam.net/feed.xml und https://susam.net/feed.xsl.

    • Das bringt mich dazu, mich zu fragen, warum ein Blog nicht einfach ein RSS-Feed sein sollte.
    • Ich vergesse immer wieder, dass XML so etwas kann. Aus irgendeinem Grund fühlt es sich seltsam an.
    • Ich mache es auf dieselbe Weise: https://adithyanair.com/feed.xml
  • Mit 19 war eines meiner ersten Projekte als professioneller Software Engineer, zwei Google Search Appliances anzupassen, die die Firma gekauft hatte.
    Das Unternehmen glaubte, dass eine Volltextsuche über ein riesiges CIFS-Dokumentenarchiv den Business-Development-Prozess verbessern würde, und gab Hunderttausende Dollar für ein Rack gelbfrontiger Dell-Server mit CentOS und Google-artigem Python aus.
    Um 2011 herum war XHTML in Mode, und die GSA funktionierte so, dass Suchergebnisse, die das Backend als XML lieferte, per XSLT in XHTML umgewandelt wurden.
    Ich nahm die Standard-Templates und baute daraus mit Assets und Markup, die ich aus gerenderten ColdFusion-Anwendungsseiten, StackOverflow und W3Schools-Tutorials stahl, ein Monster, das ungefähr wie ein Intranet-Portal der Firma aussah.
    Danach kontaktierten mich auf LinkedIn mehrere DoD-Auftragnehmer wegen meiner „XML-Expertise“ und wollten mich für Dokumentenmodernisierungsprojekte gewinnen; ich lernte schnell, dass ich diese Erfahrung aus meinem Lebenslauf streichen sollte.
    Wenn man seufzend ein Array von TypeScript-Interfaces, das aus einer JSON-Antwort deserialisiert wurde, in JSX durchläuft, kann man an mich denken, der dasselbe mit XSLT gemacht hat.

  • Viele Leute beschweren sich, XML sei geschwätzig, und aus der Ferne wirkt es kompliziert, aber ich mag, dass man auf XML-Basis gute Dateiformate bauen, sie mit DTD validieren und bei Bedarf per XSLT in ein für Menschen gut lesbares Format bringen kann.
    XML ist wie C++ unter den textbasierten Dateiformaten. Es ist ausgereift, hat Batterien inklusive, ist mächtig und lässt sich, wenn man will, aus jeder Sprache verwenden.
    Es ist Mode geworden, auf XML zu schimpfen, so wie man auf alte, ausgereifte Sprachen wegen ihrer jeweiligen Seltsamkeiten schimpft. Wenn es nicht zum Einsatzzweck passt, benutzt man es eben nicht – aber man muss es nicht wie ein Monster behandeln.

    • Ich frage mich, warum DTD und nicht XSD verwendet wird.
  • Als Beispiel dafür, wie weit XML und XSLT Anfang der 2000er gingen: Eine Firma, bei der ich früher arbeitete, baute einen ASIC, der XML mit Leitungsgeschwindigkeit parste und XSLT nativ auf dem Chip verarbeitete.
    Man erwartete nämlich, dass die Zukunft des Internets vollständig XML/XSLT sein würde. Intel übernahm die Firma, und die interne Technik floss in SSE-Beschleuniger ein.

    • Man stellt sich vor, wie schnell Websites gerendert hätten, wenn es diesen Weg genommen hätte.
    • IBM verkauft immer noch Hardware, die grob zu dieser Beschreibung passt: das DataPower Gateway.
  • Dass „XSLT nativ im Browser läuft“, fühlt sich wie Magie an – erstaunlich.
    Das letzte Mal habe ich XSLT vor etwa 20 Jahren benutzt, damals aber über mehrere Jahre hinweg sehr intensiv. Zu der Zeit brauchte man, um es zum Laufen zu bringen, einen riesigen, wackeligen Enterprise-Java-Turm, was der Eleganz von XSLT selbst etwas nahm.
    Wenn XSLT aber tatsächlich im Browser läuft, dann lag der heilige Gral der überall hostbaren statischen Templates die ganze Zeit direkt vor unserer Nase.

    • Browser unterstützen nur XSLT v1.0, und soweit ich gehört habe, gab es auch schon Überlegungen, das abzuschaffen.
      Wenn stattdessen v3-Unterstützung käme, ließen sich statische Webseiten mit nativer Template-Unterstützung wohl leichter ausliefern.
    • Ein „riesiger, wackeliger Enterprise-Java-Turm“ war es nun auch wieder nicht. Mit Tomcat und ein paar Apache-Bibliotheken ließ sich das gut nutzen.
      Das CMS spuckte XML-Dateien mit eingebettetem HTML aus, und das ließ sich sehr gut cachen. Personalisierung und HTML/JS-Rendering wurden serverseitig zusammen mit einem Caching-Proxy erledigt.
      Die XSL-Transformation lief hinter dem Cache und war schnell genug, um viel Traffic zu bewältigen. Der Zweck von XML war hier, fertiges HTML als Blob einzubetten und nur die Teile, die Personalisierung brauchten, als XML-Tags zu belassen.
      Die abschließende Transformation war ziemlich schnell; entscheidend war, die Ausgabe des XSL-Transformers nicht in einem vollständigen Speicherpuffer zu sammeln, sondern direkt in den Response-Output-Stream fließen zu lassen. Bei großen Responses ist das auch heute noch eine gute Technik, die viele Frameworks verpassen, weil sie standardmäßig Memory-Buffering verwenden.
      Heute kann man natürlich mit wasm im Browser laufen lassen, was man will. Damals war JavaScript aber ein Durcheinander, und Designer lieferten bestenfalls Photoshop-Dateien ab. Die musste man in Frames und Tabellen zerschneiden, und zu der Zeit, als Google Maps und Gmail gerade erschienen, bauten wir eine ziemlich JavaScript-lastige CMS-UI, die sowohl Netscape als auch Internet Explorer unterstützen musste.
    • 2008 habe ich an einer Website gearbeitet, die XSLT im Browser nutzte; die Unterstützung selbst scheint bis in die frühen 2000er zurückzureichen.
    • XSLT funktioniert, aber die Browser scheinen alle an alten Versionen der Spezifikation festzuhängen.
      In Firefox gibt es einen besonders lästigen Bug: Wenn man disable-output-escaping braucht, um HTML im Dokument als echten DOM rendern zu lassen, funktioniert es nicht richtig und wird als roher HTML-Text gerendert.
    • Dass dafür ein Enterprise-Java-Turm nötig gewesen sein soll, verstehe ich nicht. In classic ASP habe ich XML mit ungefähr drei Zeilen VBScript transformiert.
  • Vor langer Zeit, in einem sehr weit entfernten dystopischen Projekt, hatte jemand eine Lösung, weil er pessimistisch war, dass das Team die Java-Entwicklung mit einem sich schnell ändernden Workbook parallel abgestimmt bekommen würde.
    Die Struktur war so: Visual Basic wandelte ein in Excel erstelltes Workbook in XML um, und XSLT-Dateien generierten daraus automatisch Java-Klassen, die die in diesem XML definierten Struts-Actions verarbeiteten.
    https://raganwald.com/2008/02/21/mouse-trap.html
    HN-Diskussion: https://news.ycombinator.com/item?id=120379 · https://news.ycombinator.com/item?id=947952