######################### Transform XML with XSLT ######################### You have an XML document and an XSLT 1.0 stylesheet, and you want the transformed output. Parse both, then apply the stylesheet. ******************** Apply a stylesheet ******************** A stylesheet is itself XML, so read it with :func:`turbohtml.parse_xml`; the source is any parsed tree. Wrap the stylesheet in :class:`turbohtml.transform.Transform` and call it with the source: .. testcode:: from turbohtml import parse_xml from turbohtml.transform import Transform style = parse_xml( '' '' '
    ' '' "
" '
  • ' "
    " ) convert = Transform(style) print(convert(parse_xml("pearapple"))) .. testoutput:: :class:`~turbohtml.transform.Transform` compiles the stylesheet once; call it on as many documents as you like. For a one-off, :func:`turbohtml.transform.transform` does both steps in a single call. ***************** Pass parameters ***************** A top-level ``xsl:param`` becomes a keyword argument. Each value is an XPath expression, so quote a string literal the way lxml does: .. testcode:: style = parse_xml( '' '' '' ', ' "" ) doc = parse_xml("World") print(Transform(style)(doc, greeting="'Hi'")) .. testoutput:: Hi, World ***************** Choose a method ***************** The stylesheet's ``xsl:output method`` picks the serialization: ``xml`` (the default, with a leading declaration unless ``omit-xml-declaration="yes"``), ``html`` (void elements stay open), or ``text`` (character data only). A malformed stylesheet, a bad expression, or a reference to an undeclared key or template raises :exc:`ValueError`; an ``xsl:message`` with ``terminate="yes"`` raises :exc:`RuntimeError`. ********************* Import a stylesheet ********************* ``xsl:import`` composes stylesheets across files. Because a parsed tree carries no location, pass the importing stylesheet's path as ``base_url`` so each ``href`` resolves against it; the imported templates join at lower import precedence, so the importer's own rules win a conflict. .. testcode:: import tempfile from pathlib import Path from turbohtml import parse_xml from turbohtml.transform import transform with tempfile.TemporaryDirectory() as folder: base = Path(folder, "base.xsl") base.write_text( '' '[]', encoding="utf-8", ) main = Path(folder, "main.xsl") main.write_text( '' '' '', encoding="utf-8", ) source = parse_xml("x") print(transform(parse_xml(main.read_text(encoding="utf-8")), source, base_url=str(main))) .. testoutput:: [x] The only features out of reach are locale-aware ``xsl:sort`` collation, ``id()`` over DTD-declared IDs, ``xsl:include``, and ``document()``. For the design, see :doc:`/explanation/xslt`; for a port from lxml, see :doc:`/migration/lxml`.