[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Better "Report Map" Function?

Subject: Re: Better "Report Map" Function?
From: "Eliot Kimber ekimber@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 6 Oct 2018 15:10:01 -0000
Re:  Better "Report Map" Function?
You're right, I failed to set a return type (which I would normally always
do). The intent is definitely to return a string.

I haven't tried to make it 100% general at this point since this was something
I hacked quickly in the context of debugging other code.

I will correct the key sorting--I knew assuming the keys were strings was not
sufficient but all the maps in my current projects only use string keys.

For handling the possible entry values, I was pretty much just adding handlers
as I needed them. For example, using this on the result of Saxon's
collection() extensions that return maps of file information made it clear
that I needed an "other" category...

Cheers,

Eliot

--
Eliot Kimber
http://contrext.com


o;?On 10/6/18, 9:49 AM, "Michael Kay mike@xxxxxxxxxxxx"
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

    I wonder if this is really what you want?

    You haven't declared a return type for the function, so there's going to
be no conversion applied, which means it's going to output a sequence of
interspersed text and element nodes. That's probably fine if the function call
always appears within xsl:value-of, but it's not very convenient if, for
example, you want to call it as an argument of contains() or substring(). I
would have thought a function that returned a string would be more useful.

    And a function that only handles map values that are maps, elements,
document nodes, single strings, single booleans, or single integers doesn't
feel very general-purpose.

    But you're right that there's probably nothing off-the-shelf that gives
you exactly what you want. For many purposes (e.g. diagnostic output) the
serialize() function with method=adaptive will be adequate, but if you want
something better then you have to do it yourself.

    Incidentally, sorting the keys of a map like this will fail if the keys
include non-ordered values such as QNames, of if they include a mixture of
strings and numbers. If you want to be sure the sort won't fail, convert keys
to strings before sorting.

    Michael Kay
    Saxonica

    > On 6 Oct 2018, at 14:33, Eliot Kimber ekimber@xxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
    >
    > 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/ca
libration-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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.