Converting between XML and JSON?

It's not clear how XML can be converted to JSON in a general way, because how would one deal with attributes? You happen not to have attributes in your XML, but that's just a special case.

Luckily, Mathematica is a great language to write ad hoc parsers in.

convert[XMLObject["Document"][{}, content_, {}]] := convert[content]
convert[XMLElement[tagName_, _, children : {__XMLElement}]] := <|tagName -> convert /@ children|>
convert[XMLElement[tagName_, _, {child_}]] := <|tagName -> child|>
ExportString[convert[xml], "JSON"]

{ "root":[ { "fair":[ { "there":[ { "fog":"balloon" }, ...


I've not been involved with XML lately, but I used to (re)define XMLObject and XMLElement to process an XML structure. It's usually received lukewarm appreciation on this site, but it seems like the sort of expression-rewriting Mathematica was built for. And in this case, it's easy:

json = Block[
   { XMLObject = Function[{#2} &],
   , XMLElement = #1 -> Replace[#3, {x_} :> x] &
   }
 , ixml
 ]
(*
{"root" -> {
   "fair" -> {
     "there" -> {
       "fog" -> "balloon",
       "flew" -> "load",
       "slipped" -> "pan",
       "shine" -> "1616809877.197722",
       "general" -> "warm",
       "stock" -> "pale"},
     "higher" -> "273906901",
     "environment" -> "673083878",
     "raw" -> "-1195497107",
     "lunch" -> "1930133836",
     "body" -> "wool"},
   "green" -> "831388325",
   "writer" -> "-465508588.16013575",
   "chest" -> "touch",
   "score" -> "-969560157",
   "aboard" -> "-1575070350"}}
*)

The above is converted to JSON with

ExportString[json, "JSON"]

If "RawJSON" is desired, convert the "JSON" string:

ExportString[ExportString[json, "JSON"], "RawJSON"]

Some consistency checks:

json === ImportString[ExportString[json, "JSON"], "JSON"]
(*  True  *)

json === ImportString[
  ImportString[ExportString[ExportString[json, "JSON"], "RawJSON"], 
   "RawJSON"], "JSON"]
(*  True  *)

ixml === (
  XMLObject["Document"][{}, #, {}] & @@ json /. 
   Rule -> (XMLElement[#1, {}, 
       Replace[#2, atom : Except[_List] :> {atom}]] &)
  )
(*  True  *)

Perhaps you can pre-process your data before feeding it in Mathematica? If so, I'd suggest you consider Data Transformer (disclaimer - I'm its developer).

It offers a number of conversion settings (with sensible defaults) so you can match the data for your purposes. You can choose how to treat XM attributes, embedded text etc.

It's available on the Mac App Store and the Microsoft Store.

Here's Data Transformer's JSON output with the default settings for your example:

{
  "root": {
    "fair": {
      "there": {
        "fog": "balloon",
        "flew": "load",
        "slipped": "pan",
        "shine": 1616809877.197722,
        "general": "warm",
        "stock": "pale"
      },
      "higher": 273906901,
      "environment": 673083878,
      "raw": -1195497107,
      "lunch": 1930133836,
      "body": "wool"
    },
    "green": 831388325,
    "writer": -465508588.16013575,
    "chest": "touch",
    "score": -969560157,
    "aboard": -1575070350
  }
}