- From: COUTHURES Alain <alain.couthures@agencexml.com>
- Date: Sat, 11 Dec 2010 15:48:25 +0100
- To: public-forms@w3.org, www-forms@w3.org
- Message-ID: <4D038F39.90209@agencexml.com>
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& b">A+B</________> <________ exml:fullname="déjà">already</________> <________ exml:fullname="________">underscores</________> </exml:noname> and * "/*/*[fullname() = 'a & 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