xproc / 3.0-steps

Repository for change requests to the standard step library and for official extension steps
10 stars 7 forks source link

Clarification of primary input to p:xslt with XSLT 3: can it be an XDM array or map #357

Closed martin-honnen closed 4 years ago

martin-honnen commented 4 years ago

In his talk at XmlPrague (now online at https://so.nwalsh.com/2020/02/15/xproc-30) Norm, when presenting the XSLT 3 code sample to transform JSON (a JSON/XDM 3.1 array of maps) to CSV, made the following comment:

It has no primary input document. Note, in particular, that I couldn’t pass the map to the step as its primary input. Maps aren’t nodes, so you can’t do that.

The p:xslt step presented then used the option for the global-context-item and an empty input source port together with a named template:

  <p:xslt template-name="convert">
    <p:with-option name="global-context-item" select="."/>
    <p:with-input port="source"><p:empty/></p:with-input>
    <p:with-input port="stylesheet" href="json2csv.xsl"/>
  </p:xslt> 

I asked on Norm's blog whether the remark about the impossibility to use a map as the primary input to p:xslt is due to his implementation or a general restriction by the spec.

On digging further, I also found the test case https://test-suite.xproc.org/tests/ab-xslt-016.html by Achim which seems to do what Norm says is not possible, namely it does seem to use a JSON map as the primary input.

Furthermore looking at https://spec.xproc.org/master/head/xproc/#json-documents it says:

Representations of JSON documents are instances of the XDM. They are maps, arrays, or atomic values

So based on Achim's test case and based on that definition of a JSON document I think the remark by Norm, based on what his implementation allows, suggests that his implementation is not yet correct in terms of dealing with XDM maps or arrays as the primary input of an XSLT 3 stylesheet in the p:xslt step and it should be possible to use the JSON result from the previous step directly as the input with e.g.

<p:xslt version="3.0" name="xslt">
            <p:with-input port="stylesheet">
               <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:map="http://www.w3.org/2005/xpath-functions/map"
 xmlns:array="http://www.w3.org/2005/xpath-functions/array"
 exclude-result-prefixes="#all"
version="3.0">

     <xsl:output method="text"/>

      <xsl:template match=".[. instance of array(*)]">
  <xsl:variable name="results" select="."/>

  <xsl:variable name="keys"
                select="map:keys(array:get(.,1))"/>
  <xsl:for-each select="$keys">
    <xsl:if test="position() gt 1">,</xsl:if>
    <xsl:text>"</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>"</xsl:text>
  </xsl:for-each>
  <xsl:text>&#10;</xsl:text>

  <xsl:for-each select="1 to array:size(.)">
    <xsl:variable name="result"
                  select="array:get($results, .)"/>
    <xsl:for-each select="$keys">
      <xsl:if test="position() gt 1">,</xsl:if>
      <xsl:text>"</xsl:text>
      <xsl:value-of select="map:get($result, .)"/>
      <xsl:text>"</xsl:text>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
  </xsl:for-each>
                  </xsl:template>
               </xsl:stylesheet>
            </p:with-input>
         </p:xslt>
xml-project commented 4 years ago

I agree with your analysis, but may be we got Norms comment wrong.

xml-project commented 4 years ago

@ndw Think we can close this, can't we?

ndw commented 4 years ago

I'll do some research.

ndw commented 4 years ago

Yes. It was a bug in my implementation that I misinterpeted. Mea culpa.