jsontreeappOpen a file

Reading XML as a tree

XML has three things JSON does not: attributes, text mixed in with children, and repeated element names. Any tool that shows XML as a JSON-shaped tree has to decide what to do with them. Here is what jsontree.app decided, and what it costs.

Attributes get an @ in front

<book id="1" lang="en">
  <title>Dune</title>
</book>
book
  @id     "1"
  @lang   "en"
  title   "Dune"

The prefix keeps attributes and child elements in one flat list without them colliding, and it is obvious at a glance which is which. An element name can never start with @ in XML, so nothing legitimate is ever mistaken for an attribute.

An element with only text becomes the text

If there are no attributes and no element children, there is nothing to keep, so the element collapses to its text:

<title>Dune</title>      becomes    title  "Dune"

Without this rule every leaf in the document would be a one key object wrapping a #text, which is technically faithful and horrible to read. When there is something else to keep, the text lands under #text alongside it.

Repeated names become an array

<catalog>
  <book>Dune</book>
  <book>Neuromancer</book>
</catalog>
catalog
  book  [ "Dune", "Neuromancer" ]

This is the rule with the sharpest edge, and it is worth knowing about. The shape depends on the data, not on the schema. One <book> gives you a string, two give you an array. If you are writing code against the result rather than just reading it, that difference will find you eventually. Every XML to JSON converter has this problem and none of them solve it without a schema.

What gets thrown away

Being honest about this matters more than the mapping itself.

Entities

The five predefined entities are decoded, along with numeric ones in both forms, so &amp;, &#65; and &#x41; all come out as the characters they mean. A DOCTYPE with an internal subset is skipped rather than interpreted, which means custom entity definitions are not expanded. This is deliberate. Expanding entities from a document you were just handed is how billion laughs works.

A note on doing this in a browser

Web Workers have no DOMParser. If you want to parse XML off the main thread, and for a large file you do, you have to bring your own scanner. That is also the only way to get progress out of it: DOMParser is a single call that tells you nothing until it is finished, so a hand written scanner is what lets a progress bar move by bytes instead of pretending.

Try it

jsontree.app reads XML with its own scanner in a worker, so the page stays alive and the progress bar is real. Errors come back with a line number and the source around them.

Open a file