Xml to json mapping call

At first glance, I thought that using XML data in javascript would be as simple as finding the xml-to-json library and turning my XML into a javascript object tree.

Now, however, I understand that it is possible to create structures in xml that are not displayed directly in json.

In particular, these are:

<parentNode> <fooNode>data1</fooNode> <barNode>data2</barNode> <fooNode>data3</fooNode> </parentNode> 

The xml-to-json tools I found convert the previous to the following:

 { parentnode:{ foonode:[ 'data1', 'data3' ], barnode:'data2' } 

}

in which the order of the child nodes has been changed. I need to keep the order of my child nodes. Anyone has a solution that is more elegant than

a) giving up the idea of ​​automatic conversion and just developing my own javascript object structure and creating code to process this particular XML schema

or

b) abandon the idea of ​​any conversion altogether and leave my XML data as an XML document that I will go through.

+4
source share
4 answers

If you need the same element name often, and you care about ordering, it might be best to stay with XML. What benefits do you expect from using JSON?

+2
source

Mappings from XML to JSON with constraints (see Converting between XML and JSON ) and mappings from JSON to XML (see JSONx as here and the IBM conversion rules ) are established. However, an XML mapping to JSON that maintains order is not yet defined. To fully capture all aspects of XML, you must express XML Infoset in JSON. if you only care about the XML elements (without processing instructions, etc.), I would choose this structure:

 [ "parentNode", { } /* attributes */ [ [ "fooNode", { }, [ "data1" ] ] [ "fooNode", { }, [ "data2" ] ] [ "fooNode", { }, [ "data3" ] ] ] ] 

I implemented the same mapping as the mapping between XML and Perl data structures that are similar to JSON with XML :: Struct . The structure also follows the MicroXML abstract data model , a simplified subset of XML.

+2
source

Why not give it a try:

 { parentNode: [ ["fooNode", "data1"], ["barNode", "data2"], ["fooNode", "data3"] ] } 

I think this would more or less solve the problem.

And yes, I think you should refuse automatic conversion if it is not flexible enough; instead, you can look for an API that makes such mappings trivial.

+1
source

I developed this recently:

(just a thought experiment)

 var someTinyInfosetSample = { "doctype": "html", "$": [ { "": "html" }, [ { "": "head" }, [ { "": "title" }, "Document title" ] ], [ { "": "body" }, [ { "": "h1" }, "Header 1" ], [ { "": "p", "class": "content" }, "Paragraph... (line 1)", [ { "": "br" } ], "... continued (line 2)" ] ] ] }; 

(at https://jsfiddle.net/YSharpLanguage/dzq4fe39 )

Quick rationale:

XML elements are the only node type (besides the document root) that accepts mixed content (text nodes and / or other elements, comments, PIs and determines the order of its child nodes, so using JSON arrays (child indexes are then 1-based, not based on 0 due to the reserved index 0 for transferring type (element) node information, but you can see that XPath node sets also use an index based on 1, btw);

XML attributes / attribute value maps do not need key ordering (attribute names) wrt. their owner, only the uniqueness of those elements in this node element; therefore, the use of the JSON object at index 0 of the container array (corresponds to the owner element);

and finally, in the end, while "is a valid JSON key in object values, this is also the case when none of the XML elements or attributes can have an empty name anyway ... hence the use of" " as a special, ordinary key to provide the element name.

And here is what it takes to turn it into HTML using my little "JSLT" (at https://jsfiddle.net/YSharpLanguage/c7usrpsL/10 ):

 var tinyInfosetJSLT = { $: [ [ [ function/*Root*/(node) { return node.$; } ], function(root) { return Per(this).map(root.$); } ], [ [ function/*Element*/(node) { return { }.toString.call(node) === "[object Array]"; } ], function(element) { var children = (element.length > 1 ? element.slice(1) : null), startTag = element[0], nodeName = startTag[""], self = this; return children ? Per("\r\n<{stag}>{content}</{etag}>\r\n").map ({ stag: Per(this).map(startTag), etag: nodeName, content: Per(children).map(function(child) { return Per(self).map(child); }).join("") }) : Per("<{stag}/>").map({ stag: Per(this).map(startTag) }); } ], [ [ function/*StartTag*/(node) { return node[""]; } ], function(startTag) { var tag = [ startTag[""] ]; for (var attribute in startTag) { if (attribute !== "") { tag.push ( Per("{name}=\"{value}\""). map({ name: attribute, value: startTag[attribute].replace('"', "&quot;") }) ); } } return tag.join(" "); } ], [ [ function/*Text*/(node) { return typeof node === "string"; } ], function(text) { return text. replace("\t", "&x09;"). replace("\n", "&x0A;"). replace("\r", "&x0D;"); } ] ] }; 

(Cf. https://jsfiddle.net/YSharpLanguage/dzq4fe39/1 )

Where

 Per(tinyInfosetJSLT).map(someTinyInfosetSample) 

gives (as a string):

 <html> <head> <title>Document title</title> </head> <body> <h1>Header 1</h1> <p class="content">Paragraph... (line 1)<br/>... continued (line 2)</p> </body> </html> 

(but the conversion can also be easily adapted to use the DOM node factory and create the actual DOM document instead of creating a string)

'NTN,

0
source

All Articles