[xsl] Better "Report Map" Function?

Subject: [xsl] Better "Report Map" Function?
From: "Eliot Kimber ekimber@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 6 Oct 2018 13:33:08 -0000
I needed a way to report the contents of maps as nicely-formatted strings using XSLT 3 and Saxon (Saxon's built-in serialization of maps did not really satisfy me).

Here's my solution:

  <xsl:function name="local:report-map">
    <xsl:param name="map" as="map(*)"/>
    <xsl:param name="level" as="xs:integer"/>
    
    <xsl:variable name="indent" as="xs:string?" 
      select="(for $i in 1 to $level return '  ') => string-join()"
    />
    <xsl:text>&#x0a;{$indent}{{</xsl:text>
    <xsl:for-each select="map:keys($map) => sort()">
      <xsl:variable name="key" select="."/>
      <xsl:variable name="value" select="map:get($map, $key)"/>
      <xsl:text>&#x0a;{$indent}  "{$key}" : </xsl:text>
      <xsl:choose>
        <xsl:when test="$value instance of map(*)">
          <xsl:text> Map:</xsl:text>
          <xsl:sequence select="local:report-map($value, $level + 3)"/>
        </xsl:when>
        <xsl:when test="$value instance of element()">
          <xsl:sequence select="$value"/>
        </xsl:when>
        <xsl:when test="$value instance of document-node()">
          <xsl:text> document-node(): {name($value/*)} - "{document-uri($value)}"</xsl:text>
        </xsl:when>
        <xsl:when test="$value instance of xs:string or $value instance of xs:boolean or $value instance of xs:integer">
          <xsl:text>"{$value}"</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>unhandled value</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
    <xsl:text>&#x0a;{$indent}}}</xsl:text>
  </xsl:function>

Which produces output like this:

{
   "baseType" : "map"
   "doc" :  document-node(): map - "file:/Users/ekimber/workspace/paccar/repo/paccar/sample_data/test-project/calibration-data/MX11_NA/calibrationSLMP_MX11_NA.ditamap"
   "engineFamilies" : "10.8M01"
   "key" : ""
   "relpath" : "calibration-data/MX11_NA/calibrationSLMP_MX11_NA.ditamap"
   "type" : "map"
 }

I'm happy with the result but wondering if there's not a more efficient/cleaner/more elegant way to do the same thing?

Cheers,

E.
--
Eliot Kimber
http://contrext.com

Current Thread