Parameterized sorting in XSLT

XSLT is used frequently for presentation purposes, for example to turn a data payload into a browser-ready HTML page. A good presentation layer is culture-aware, and this is where things get interesting.

By default, the xsl:sort element will sort based on the system default. This may not be what you want; your front-end, middle-tier and back-end might have very different default settings, and you'll want to pick the right one.

Thankfully this is straightforward to accomplish with stylesheets. You can simply use a parameter to indicate which language you want to use for sorting, and then refer to that parameter in your xsl:sort elements.

You can save the following content to a .js file and try it out using cscript.exe. The bold bits show how console input makes its way to the transformed stylesheet.

I've included a "sample session" in the comments below. Note how in traditional Spanish, "choza" sorts aftoer "cosa", because the 'ch' as a pair sorts after 'c', but in modern Spanish (eg Argentina) and English, 'h' sorts before 'o' on its own.

function createDocumentFromText(xmlText) {
  var result = new ActiveXObject("Msxml2.DOMDocument.6.0");
  result.async = false;
  return result;

function createXslProcessorFromText(xmlText) {
  var doc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.6.0");
  doc.async = false;
  var result = new ActiveXObject("Msxml2.XSLTemplate.6.0");
  result.stylesheet = doc;
  return result;

// Main.
WScript.Echo("Write the language code for the transform; empty to quit");
var doc = createDocumentFromText("<a><b>cosa</b><b>choza</b></a>");
var xsl = createXslProcessorFromText(
  "<xsl:stylesheet version='1.0' xmlns:xsl=''>" +
  " <xsl:param name='sort' />" +
  " <xsl:template match='/'>" +
  "  <a>" +
  "   <xsl:for-each select='a/b'><xsl:sort select='text()' lang='{$sort}' />" +
  "    <b><xsl:value-of select='text()' /></b>" +
  "   </xsl:for-each>" +
  "  </a>" +
  " </xsl:template>" +

var done = false;
do {
  var line = WScript.StdIn.ReadLine();
  if (line.length == 0) {
    done = true;
  } else {
    try {
      var processor = xsl.createProcessor();
      processor.input = doc;
      processor.addParameter("sort", line, "");
    } catch (e) {
} while (!done);

// Output:
// Write the language code for the transform; empty to quit
// en
// <?xml version="1.0"?><a><b>choza</b><b>cosa</b></a>
// es
// <?xml version="1.0"?><a><b>cosa</b><b>choza</b></a>
// es-ar
// <?xml version="1.0"?><a><b>choza</b><b>cosa</b></a>


Comments (0)

Skip to main content