jsonxmlelixirelixir-mixelixir-iex

Parse XML to JSON Elixir


anyone knows How to convert xml into json. I tried Sweetyxml but its not converting xml into json.

Using this gist https://gist.github.com/spint/40717d4e6912d8cea929 Reading json

{:ok, xmldoc} = File.read(Path.expand("/Users/sohaibanwar/Desktop/unconfirmed_order.xml"))
{doc, []} = xmldoc |> to_charlist() |> :xmerl_scan.string() 
After parsing (in screenshot), but not getting right answer

YML FILE I am using

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order>
    <orderId>35267684</orderId>
    <orderToken>fa74171d-f54a-4e76-bcf2-2dd284ac6450</orderToken>
    <brokerTicketId>169855177</brokerTicketId>
    <section>SEC1</section>
    <row>N</row>
    <seats/>
    <notes>Limited view. Please note that you will need to use an iOS or Android mobile device to gain entry to your event.</notes>
    <quantity>2</quantity>
    <cost>324.00</cost>
    <event>Dave Matthews Band (Rescheduled from 7/17/2020, 7/16/2021)</event>
    <eventDate>2021-08-20 19:30:00</eventDate>
    <orderDate>2021-06-18 05:43:13</orderDate>
    <expectedShipDate>2021-06-18 00:00:00</expectedShipDate>
    <venue>Xfinity Center - MA - Mansfield, MA</venue>
    <status>UNCONFIRMED</status>
    <purchaseOrderId>35088971</purchaseOrderId>
    <electronicDelivery>false</electronicDelivery>
    <passThrough></passThrough>
    <listingId>3359267717</listingId>
    <productionId>3412459</productionId>
    <eventId>218</eventId>
    <zone>false</zone>
    <barCodesRequired>false</barCodesRequired>
    <transferViaURL>true</transferViaURL>
    <instantTransfer>false</instantTransfer>
    <instantFlashSeats>false</instantFlashSeats>
</order>

Required Results You can paster the XML here to get the required answer

{
  "order": {
    "orderId": 35267684,
    "orderToken": "fa74171d-f54a-4e76-bcf2-2dd284ac6450",
    "brokerTicketId": 169855177,
    "section": "SEC1",
    "row": "N",
    "seats": "",
    "notes": "Limited view. Please note that you will need to use an iOS or Android mobile device to gain entry to your event.",
    "quantity": 2,
    "cost": 324,
    "event": "Dave Matthews Band (Rescheduled from 7/17/2020, 7/16/2021)",
    "eventDate": "2021-08-20 19:30:00",
    "orderDate": "2021-06-18 05:43:13",
    "expectedShipDate": "2021-06-18 00:00:00",
    "venue": "Xfinity Center - MA - Mansfield, MA",
    "status": "UNCONFIRMED",
    "purchaseOrderId": 35088971,
    "electronicDelivery": false,
    "passThrough": "",
    "listingId": 3359267717,
    "productionId": 3412459,
    "eventId": 218,
    "zone": false,
    "barCodesRequired": false,
    "transferViaURL": true,
    "instantTransfer": false,
    "instantFlashSeats": false
  }
}

Solution

  • Well, if your question is How to convert xml to json in Elixir the answer is fairly simple: use https://github.com/homanchou/elixir-xml-to-map and JSON encoder of your choice:

    def xml2json(path) do
      File.read!(path)
      |> XmlToMap.naive_map()
      |> Jason.encode!()
    end
    

    The problem with this answer is that XML is not isomorphic to map (you have both tags and attributes in XML and you don't in map or JSON), so the better way will be to use SweetXML (or :xmerl) and do xmap with a proper match like here (code is from SweetXML examples - https://github.com/kbrw/sweet_xml#examples):

    result = doc |> xmap(
      matchups: [
        ~x"//matchups/matchup"l,
        name: ~x"./name/text()",
        winner: [
          ~x".//team/id[.=ancestor::matchup/@winner-id]/..",
          name: ~x"./name/text()"
        ]
      ],
      last_matchup: [
        ~x"//matchups/matchup[last()]",
        name: ~x"./name/text()",
        winner: [
          ~x".//team/id[.=ancestor::matchup/@winner-id]/..",
          name: ~x"./name/text()"
        ]
      ]
    )
    assert result == %{
      matchups: [
        %{name: 'Match One', winner: %{name: 'Team One'}},
        %{name: 'Match Two', winner: %{name: 'Team Two'}},
        %{name: 'Match Three', winner: %{name: 'Team One'}}
      ],
      last_matchup: %{name: 'Match Three', winner: %{name: 'Team One'}}
    }
    

    Another option is to use https://github.com/willemdj/erlsom and do manual travers over tuple tree it emits from the simple_form call. Note you will have to handle XMLNS and attr/value problem anyways.