Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special JSON↔XML conversion params/rules for p:cast-content-type #266

Closed
gimsieke opened this issue Nov 14, 2019 · 4 comments
Closed

Special JSON↔XML conversion params/rules for p:cast-content-type #266

gimsieke opened this issue Nov 14, 2019 · 4 comments

Comments

@gimsieke
Copy link
Contributor

@gimsieke gimsieke commented Nov 14, 2019

I’d like to specify that the parameters of p:cast-content-type are not entirely implementation-defined.

For JSON→XML, a parameter c:vocab or similar with the values 'c:param-set' and 'c:document-properties' should be supported. The effect of this is that a JSON map will be converted to c:param-set and c:document-properties, respectively.

If the input map (= the JSON document) does not comply with the rules for parameters or document properties, an error should be raised.

If a value of the input map is itself a map or an array, it should be converted as fn:map and fn:array, respectively (that is, the default fn:json-to-xml() output).

The type of a value should always be indicated by an xsi:type attribute.

Example:

<p:identity>
  <p:with-input select="map{'foo':'bar', 'mappy':map{'foo':'bar'} }"/>
</p:identity><!-- Output: JSON document -->
<p:cast-content-type content-type="application/xml" parameters="{'c:vocab':'c:param-set'}"/>
⇒
<c:param-set>
  <c:param name="foo" value="bar" xsi:type="xs:string"/>
  <c:param name="mappy" xsi:type="map(xs:string,xs:string)">
    <map xmlns="http://www.w3.org/2005/xpath-functions">
      <string key="foo">bar</string>
    </map>
  </c:param>
</c:param-set>

For the other way round, when c:param-set and c:document-properties documents are cast as JSON, the conversion should create maps from them (rather than raise an error that it expects fn:map or fn:array documents).


See #16, #30, and xproc/3.0-specification#910

@gimsieke

This comment has been minimized.

Copy link
Contributor Author

@gimsieke gimsieke commented Nov 21, 2019

I tried to come up with XSLT that converts a parameter map map(xs:QName, item()*) into a c:param-set document.
I thought it would be easy because I can run fn:json-to-xml() on the map and then further process it. Then I was reminded that the argument to fn:json-to-xml() is not a map, but a string representing a serialized JSON document.
I declared these variables:

<xsl:variable name="doc" as="document-node()">
  <xsl:document>
    <doc attribute="value"/>
  </xsl:document>
</xsl:variable>

<xsl:variable name="param1" as="map(xs:QName, item()*)" 
  select="map{xs:QName('xs:name'): 'foo', 
              xs:QName('bar'): map{'baz': ['a', 1]},
              xs:QName('third'): ($doc, $doc/*/@*)}"/>

I realized that I couldn’t serialize the map value of 'third' to JSON because

SERE0023: JSON serialization: cannot handle a sequence of length 2

So I can use some try/catch and revert to the adaptive method if serialization to JSON fails.

But anyway, even if I managed to serialize it as JSON, I’d lose the type information. So I’ll probably end up with a detailed inspection of the content and try/catch for every key and value of the nested maps.

This won’t probably fit into half a page of XSLT code.

So I’ll preliminarily surrender (because I also need to walk the dog, she’s been waiting for 30 minutes now) and look at my options afterwards.

But I may end up saying that a reasonable function may only be specified to work for a limited set of map values, which is probably what you already have found out.

gimsieke added a commit to xproc/Workshop-2019-11 that referenced this issue Nov 21, 2019
@gimsieke

This comment has been minimized.

Copy link
Contributor Author

@gimsieke gimsieke commented Nov 21, 2019

See https://github.com/xproc/Workshop-2019-11/blob/master/xsl/param-set.xsl

Input:

<xsl:variable name="doc" as="document-node()">
  <xsl:document>
    <doc attribute="value"/>
  </xsl:document>
</xsl:variable>

<xsl:variable name="param1" as="map(xs:QName, item()*)" 
  select="map{xs:QName('num'): 43.0,
              xs:QName('xs:name'): 'foo', 
              xs:QName('foo:test'): ($doc, 'f'), 
              xs:QName('foo:test0'): ([45.7, 'g', true()], [-2, 4.3]), 
              xs:QName('foo:test1'): [45.7, 'g', true()], 
              xs:QName('foo:test2'): ($doc, $doc/*), 
              xs:QName('foo:test3'): [[45.7, 'g', true()], [-2, 4.3]], 
              xs:QName('foo:test4'): (([45.7, 'g', true()]), ([-2, 4.3])), 
              xs:QName('bar'): map{'baz': ['a', 1]},
              xs:QName('third'): ($doc, $doc/*/@*)}"/>

Output:

<c:param-set xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:foo="http://acme.com/foo"
             xmlns:xpu="http://xproc.org/ns/util"
             xmlns:c="http://www.w3.org/ns/xproc-step"
             xmlns:map="http://www.w3.org/2005/xpath-functions/map">
   <c:param name="bar" method="json-to-xml">
      <map xmlns="http://www.w3.org/2005/xpath-functions">
         <array key="baz">
            <string>a</string>
            <number>1</number>
         </array>
      </map>
   </c:param>
   <c:param name="foo:test"
            method="adaptive"
            value="&lt;doc xmlns:xs=&#34;http://www.w3.org/2001/XMLSchema&#34; xmlns:foo=&#34;http://acme.com/foo&#34; xmlns:xpu=&#34;http://xproc.org/ns/util&#34; xmlns:c=&#34;http://www.w3.org/ns/xproc-step&#34; xmlns:map=&#34;http://www.w3.org/2005/xpath-functions/map&#34; attribute=&#34;value&#34;/&gt;&#xA;&#34;f&#34;"/>
   <c:param name="foo:test0" method="json-to-xml">
      <array xmlns="http://www.w3.org/2005/xpath-functions">
         <number>45.7</number>
         <string>g</string>
         <boolean>true</boolean>
      </array>
      <array xmlns="http://www.w3.org/2005/xpath-functions">
         <number>-2</number>
         <number>4.3</number>
      </array>
   </c:param>
   <c:param name="foo:test1" method="json-to-xml">
      <array xmlns="http://www.w3.org/2005/xpath-functions">
         <number>45.7</number>
         <string>g</string>
         <boolean>true</boolean>
      </array>
   </c:param>
   <c:param name="foo:test2" method="xml">
      <doc attribute="value"/>
      <doc attribute="value"/>
   </c:param>
   <c:param name="foo:test3" method="json-to-xml">
      <array xmlns="http://www.w3.org/2005/xpath-functions">
         <array>
            <number>45.7</number>
            <string>g</string>
            <boolean>true</boolean>
         </array>
         <array>
            <number>-2</number>
            <number>4.3</number>
         </array>
      </array>
   </c:param>
   <c:param name="foo:test4" method="json-to-xml">
      <array xmlns="http://www.w3.org/2005/xpath-functions">
         <number>45.7</number>
         <string>g</string>
         <boolean>true</boolean>
      </array>
      <array xmlns="http://www.w3.org/2005/xpath-functions">
         <number>-2</number>
         <number>4.3</number>
      </array>
   </c:param>
   <c:param name="num" value="43"/>
   <c:param name="third"
            method="adaptive"
            value="&lt;doc xmlns:xs=&#34;http://www.w3.org/2001/XMLSchema&#34; xmlns:foo=&#34;http://acme.com/foo&#34; xmlns:xpu=&#34;http://xproc.org/ns/util&#34; xmlns:c=&#34;http://www.w3.org/ns/xproc-step&#34; xmlns:map=&#34;http://www.w3.org/2005/xpath-functions/map&#34; attribute=&#34;value&#34;/&gt;&#xA;attribute=&#34;value&#34;"/>
   <c:param name="xs:name" value="foo"/>
</c:param-set>

The fallback method is always the adaptive serialization which cannot, in general, be inverted to its original map value.

An issue with adaptive serializations might be that the serialized string creates long attributes. In order to avoid this, the @value attributes with adaptively serialized strings can be left out since they aren’t very useful anyway.

c:param/@xsi:type attributes would be nice, at least for xs:anyAtomicType values.

@ndw

This comment has been minimized.

Copy link
Collaborator

@ndw ndw commented Jan 2, 2020

At the 2 January 2020 editor's call, we decided not to do this.

@ndw ndw closed this Jan 2, 2020
@gimsieke

This comment has been minimized.

Copy link
Contributor Author

@gimsieke gimsieke commented Jan 2, 2020

I will roll my own step using this XSLT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.