Proposition for JSON internal storage for XForms

Hello,

Please find below my proposition for an internal storage in XML 1.0 for 
JSON objects allowing intuitive XPath expressions.

I'm writing a paper for XML Prague 2011 about implementing this in 
XSLTForms. This is the corresponding extract.

Thank you for your feedbacks.

-Alain
------------------------------------------------------------------------


    Constraints


      Reversibility

JSON objects have to be serialized identically to the original ones when 
not modified by controls.


      XPath Full Support

New XPath extension functions should be enough to guaranty a full support.

Whenever extra elements are required for internal storage, their number 
should be minimal.

Javascript notation to retrieve an item in a array ([/pos/] where /pos/ 
starts from 0) should be almost preserved ([/pos/] where /pos/ starts 
from 1).


      XML Schema conformance

XML Schema Recommendation already defines the xsi:type and the xsi:nil 
attributes and they are supported in the XForms Recommendation. The 
xsd:maxOccurs attribute enables to specify how many occurences there 
might be for an element.


    Proposed Representation of JSON Objects With XML 1.0


      Elements, Attributes and Namespaces

Elements are used for JSON values within the empty namespace.

Meta data are stored in attributes within a specific namespace.

Extra elements are limited and always in a specific namespace.


      Extra Document Element

XML 1.0 requires a unique document element so such an element is always 
added.

Example:

{ a: "stringA", b: { c: "stringC", d: "stringD" } }

would be serialized as:

<exml:noname xmlns:exml="http://www.agencexml.com/exml" xmlns="">
  <a>stringA</a>
  <b>
    <c>stringC</c>
    <d>stringD</d>
  </b>
</exml:noname>

and

    *

      "/*/a" equals 'stringA'

    *

      "/*/b/c" equals 'stringC'

    *

      "/*/b/d" equals 'stringD'


      JSON Names

JSON names which cannot be used as XML names are replaced by '________' 
in the empty namespace.

An extra attribute is used to store the JSON name and the new XPath 
functions fullname() and local-fullname() are created to return its value.

Example:

{ "a&  b": "A+B", "déjà": "already", "________": "undescores" }

are represented as:

<exml:noname xmlns:exml="http://www.agencexml.com/exml"
              xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
              xmlns:exsi="http://www.agencexml.com/exi" xmlns="">
  <________ exml:fullname="a&amp; b">A+B</________>
  <________ exml:fullname="déjà">already</________>
  <________ exml:fullname="________">underscores</________>
</exml:noname>

and

    *

      "/*/*[fullname() = 'a &amp; b']" equals 'A+B'

    *

      "local-fullname(/*/*[1])" equals 'a & b'

    *

      "/*/*[fullname() = 'déjà']" equals 'already'

    *

      "local-fullname(/*/*[2])" equals 'déjà'

    *

      "/*/________[fullname() = '________']" equals 'underscores'


      JSON Datatypes

For each Javascript datatype, the most approaching XSD type is 
automatically associated. XForms bindings have to be used to adjust more 
precisely the effective datatype.

Example:

{ a: "string"+"A", b: 42, c: new Date(2011,3,26), d: true }

would be serialized as:

<exml:noname xmlns:exml="http://www.agencexml.com/exml"
              xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns="">
  <a>stringA</a>
  <b xsi:type="xsd:double">42</b>
  <c xsi:type="xsd:dateTime">2011-03-26T00:00:00Z</c>
  <d xsi:type="xsd:boolean">true</d>
</exml:noname>


      JSON Named Arrays

Arrays are modeled with an extra attribute. Empty arrays require another 
attribute because, if not, there would be an ambiguity for an array with 
just the empty string as element.

Extra XPath functions might be helpful:

    *

      is-array(/node/) which might be defined as
      "count(/node/[@exsi:maxOccurs = 'unbounded']) != 0"

    *

      array-length(/node/) which might be defined as
      "count(/node/[@exsi:maxOccurs = 'unbounded' and @xsi:nil != 'true'])"

Example:

{ a: ["stringA", 42], b: [], c: [""] }

would be serialized as:

<exml:noname xmlns:exml="http://www.agencexml.com/exml"
              xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
              xmlns:exsi="http://www.agencexml.com/exi" xmlns="">
  <a exsi:maxOccurs="unbounded">stringA</a>
  <a exsi:maxOccurs="unbounded" xsi:type="xsd:double">42</a>
  <b exsi:maxOccurs="unbounded" xsi:nil="true"/>
  <c exsi:maxOccurs="unbounded"/>
</exml:noname>

and

    *

      "is-array(/*/a)" equals true()

    *

      "array-length(/*/a)" equals 2

    *

      "/*/a[1]" equals 'stringA'

    *

      "/*/a[2]" equals '42'

    *

      "is-array(/*/b)" equals true()

    *

      "array-length(/*/b)" equals 0

    *

      "is-array(/*/c)" equals true()

    *

      "array-length(/*/c)" equals 1

    *

      "/*/c[1]" equals ''


      JSON Unnamed Arrays

An element with a reserved name in a specific namespace has to be used.

Example:

[ ["stringA", 42], [], [[]], { c: "stringC1", d: "stringD1" }, { c: "stringC2", d: "stringD2" } ]

would be serialized as:

<exml:noname xmlns:exml="http://www.agencexml.com/exml"
              xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
              xmlns:exsi="http://www.agencexml.com/exi" xmlns="">
  <exml:noname exsi:maxOccurs="unbounded">
    <exml:noname exsi:maxOccurs="unbounded">stringA</exml:noname>
    <exml:noname exsi:maxOccurs="unbounded" xsi:type="xsd:double">42</exml:noname>
  </exml:noname>
  <exml:noname exsi:maxOccurs="unbounded">
    <exml:noname exsi:maxOccurs="unbounded" xsi:nil="true"/>
  </exml:noname>
  <exml:noname exsi:maxOccurs="unbounded">
    <exml:noname exsi:maxOccurs="unbounded">
     <exml:noname exsi:maxOccurs="unbounded" xsi:nil="true"/>
    </exml:noname>
  </exml:noname>
  <exml:noname exsi:maxOccurs="unbounded">
    <c>stringC1</c>
    <d>stringD1</d>
  </exml:noname>
  <exml:noname exsi:maxOccurs="unbounded">
    <c>stringC2</c>
    <d>stringD2</d>
  </exml:noname>
</exml:noname>

and

    *

      "/*/*[1]/*[1]" equals 'stringA'

    *

      "/*/*[1]/*[2]" equals '42'

    *

      "is-array(/*/*[2])" equals true()

    *

      "is-array(/*/*[3]/*[1])" equals true()

    *

      "/*/*/c[../d = 'stringD1']" equals 'stringC1'

    *

      "/*/*[c = 'stringC2']/d" equals 'stringD2'


      XPath Engine Proposed Enhancements

When possible, XPath engine modifications can simplify expressions for 
JSON objects:

    *

      non-XML names in expressions could be quoted with character `
      (reverse quote) to avoid predicates with fullname() calls

    *

      name() and local-name() functions could be extended to support
      fullname() and local-fullname() functions and return '________'
      just when true

    *

      name() and local-name() functions could be modified to return ''
      (empty string) instead of, respectively, 'exml:noname' and 'noname'

    *

      "/*/" used for "/exml:noname/" could be simplified as just "/"'

    *

      "*" used for "exml:noname" could be written ``

    *

      "*" used for "exml:noname" before a predicate could even be omitted

Received on Saturday, 11 December 2010 14:49:37 UTC