XML XSLT Parameters and Modes
A stylesheet parameter lets the caller choose a threshold without rewriting source code. A mode selects a separate family of template rules.
How it works
Use a global parameter for a report input and a mode when the same source node needs different output in different passes. Parameters are values rather than text substitutions inside the stylesheet. In this first listing the parameter has an explicit default, so the complete example runs without caller arguments. Application calls should pass strings with the API’s safe string-parameter mechanism rather than construct XPath source from unknown input.
Run the code
Use Python 3 with lxml 6.1.1 in a separate virtual environment. The complete listing embeds its own XML and any schema or stylesheet; run python parameters-modes.py. It does not need Apache or MySQL. The shared restrictive parse function rejects declarations for untrusted input. The trusted DTD/entity and streaming lessons explicitly explain their separate fixed-input boundaries.
Download the complete parameters-modes.py source. Keep each lab in its own folder. Sources are served as text, not as public executable server scripts. Review the starting setup.
Example
from lxml import etree as E
class DenyExternal(E.Resolver):
def resolve(self, url, public_id, context):
raise ValueError("External resources are disabled")
def parse(text):
if "<!DOCTYPE" in text.upper() or "<!ENTITY" in text.upper():
raise ValueError("Declarations are disabled for untrusted XML")
parser = E.XMLParser(resolve_entities=False, load_dtd=False,
no_network=True, huge_tree=False)
parser.resolvers.add(DenyExternal())
return E.fromstring(text.encode("utf-8"), parser)
source = "<exchange region=\"west\">\n <packet id=\"p1\" available=\"true\"><name>Marigold</name><quantity>12</quantity><category>flower</category></packet>\n <packet id=\"p2\" available=\"false\"><name>Fenugreek</name><quantity>0</quantity><category>herb</category></packet>\n <packet id=\"p3\" available=\"true\"><name>Basil</name><quantity>7</quantity><category>herb</category></packet>\n</exchange>"
root = parse(source)
style_source = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n <xsl:output method=\"text\" omit-xml-declaration=\"yes\"/>\n <xsl:param name=\"minimum\" select=\"8\"/>\n <xsl:template match=\"/\"><xsl:apply-templates select=\"exchange/packet[number(quantity) >= $minimum]\" mode=\"label\"/></xsl:template>\n <xsl:template match=\"packet\" mode=\"label\"><xsl:value-of select=\"name\"/></xsl:template>\n</xsl:stylesheet>"
transform = E.XSLT(parse(style_source), access_control=E.XSLTAccessControl.DENY_ALL)
print(str(transform(root)), end="")
Expected result
Marigold
Only Marigold meets the default minimum of eight. The label mode chooses a template specifically intended for this output. The same stylesheet could have another mode that emits a detailed record.
Check the exact contract in the XML specification, XPath 1.0, the XSD 1.0 primer, lxml validation documentation and Saxon’s processor documentation.