简体   繁体   中英

Parse XML to JSON Elixir

anyone knows How to parse 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

<?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 https://jsonformatter.org/xml-parser

iex(10)> parse(xmldoc)              
{:xmlElement, :order, :order, [], {:xmlNamespace, [], []}, [], 1,
 [],
 [
   {:xmlText, [order: 1], 1, [], '\n    ', :text},
   {:xmlElement, :orderId, :orderId, [], {:xmlNamespace, [], []},
    [order: 1], 2, [],
    [
      {:xmlText, [orderId: 2, order: 1], 1, [], '35267684',
       :text}
    ], [], '/Users/sohaibanwar/Documents/elixir_project/tac4',
    :undeclared},
   {:xmlText, [order: 1], 3, [], '\n    ', :text},
   {:xmlElement, :orderToken, :orderToken, [],
    {:xmlNamespace, [], []}, [order: 1], 4, [],
    [
      {:xmlText, [orderToken: 4, order: 1], 1, [],
       'fa74171d-f54a-4e76-bcf2-2dd284ac6450', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 5, [], '\n    ', :text},
   {:xmlElement, :brokerTicketId, :brokerTicketId, [],
    {:xmlNamespace, [], []}, [order: 1], 6, [],
    [
      {:xmlText, [brokerTicketId: 6, order: 1], 1, [],
       '169855177', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 7, [], '\n    ', :text},
   {:xmlElement, :section, :section, [], {:xmlNamespace, [], []},
    [order: 1], 8, [],
    [{:xmlText, [section: 8, order: 1], 1, [], 'SEC1', :text}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 9, [], '\n    ', :text},
   {:xmlElement, :row, :row, [], {:xmlNamespace, [], []},
    [order: 1], 10, [],
    [{:xmlText, [row: 10, order: 1], 1, [], 'N', :text}], [],
    :undefined, :undeclared},
   {:xmlText, [order: 1], 11, [], '\n    ', :text},
   {:xmlElement, :seats, :seats, [], {:xmlNamespace, [], []},
    [order: 1], 12, [], [], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 13, [], '\n    ', :text},
   {:xmlElement, :notes, :notes, [], {:xmlNamespace, [], []},
    [order: 1], 14, [],
    [
      {:xmlText, [notes: 14, order: 1], 1, [],
       'Limited view. Please note that you will need to use an iOS or Android mobile device to gain entry to your event.',
       :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 15, [], '\n    ', :text},
   {:xmlElement, :quantity, :quantity, [], 
    {:xmlNamespace, [], []}, [order: 1], 16, [],
    [{:xmlText, [quantity: 16, order: 1], 1, [], '2', :text}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 17, [], '\n    ', :text},
   {:xmlElement, :cost, :cost, [], {:xmlNamespace, [], []},
    [order: 1], 18, [],
    [{:xmlText, [cost: 18, order: 1], 1, [], '324.00', :text}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 19, [], '\n    ', :text},
   {:xmlElement, :event, :event, [], {:xmlNamespace, [], []},
    [order: 1], 20, [],
    [
      {:xmlText, [event: 20, order: 1], 1, [],
       'Dave Matthews Band (Rescheduled from 7/17/2020, 7/16/2021)',
       :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 21, [], '\n    ', :text},
   {:xmlElement, :eventDate, :eventDate, [],
    {:xmlNamespace, [], []}, [order: 1], 22, [],
    [
      {:xmlText, [eventDate: 22, order: 1], 1, [],
       '2021-08-20 19:30:00', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 23, [], '\n    ', :text},
   {:xmlElement, :orderDate, :orderDate, [],
    {:xmlNamespace, [], []}, [order: 1], 24, [],
    [
      {:xmlText, [orderDate: 24, order: 1], 1, [],
       '2021-06-18 05:43:13', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 25, [], '\n    ', :text},
   {:xmlElement, :expectedShipDate, :expectedShipDate, [],
    {:xmlNamespace, [], []}, [order: 1], 26, [],
    [
      {:xmlText, [expectedShipDate: 26, order: 1], 1, [],
       '2021-06-18 00:00:00', ...}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 27, [], '\n    ', :text},
   {:xmlElement, :venue, :venue, [], {:xmlNamespace, [], []},
    [order: 1], 28, [], [{:xmlText, [venue: 28, ...], 1, ...}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 29, [], '\n    ', :text},
   {:xmlElement, :status, :status, [], {:xmlNamespace, [], []},
    [order: 1], 30, [], [{:xmlText, ...}], [], :undefined, ...},
   {:xmlText, [order: 1], 31, [], '\n    ', :text},
   {:xmlElement, :purchaseOrderId, :purchaseOrderId, [],
    {:xmlNamespace, [], []}, [order: 1], 32, [], [...], ...},
   {:xmlText, [order: 1], 33, [], '\n    ', :text},
   {:xmlElement, :electronicDelivery, :electronicDelivery, [],
    {:xmlNamespace, [], ...}, [order: 1], 34, ...},
   {:xmlText, [order: 1], 35, [], '\n    ', :text},
   {:xmlElement, :passThrough, :passThrough, [], {...}, ...},
   {:xmlText, [order: 1], 37, [], ...},
   {:xmlElement, :listingId, :listingId, ...},
   {:xmlText, [...], ...},
   {:xmlElement, ...},
   {...},
   ...
 ], [], '/Users/sohaibanwar/Documents/elixir_project/tac4',
 :undeclared}
iex(11)> xpath(xmldoc)     
** (CompileError) iex:11: undefined function xpath/1

iex(11)> parse(xmldoc)
{:xmlElement, :order, :order, [], {:xmlNamespace, [], []}, [], 1,
 [],
 [
   {:xmlText, [order: 1], 1, [], '\n    ', :text},
   {:xmlElement, :orderId, :orderId, [], {:xmlNamespace, [], []},
    [order: 1], 2, [],
    [
      {:xmlText, [orderId: 2, order: 1], 1, [], '35267684',
       :text}
    ], [], '/Users/sohaibanwar/Documents/elixir_project/tac4',
    :undeclared},
   {:xmlText, [order: 1], 3, [], '\n    ', :text},
   {:xmlElement, :orderToken, :orderToken, [],
    {:xmlNamespace, [], []}, [order: 1], 4, [],
    [
      {:xmlText, [orderToken: 4, order: 1], 1, [],
       'fa74171d-f54a-4e76-bcf2-2dd284ac6450', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 5, [], '\n    ', :text},
   {:xmlElement, :brokerTicketId, :brokerTicketId, [],
    {:xmlNamespace, [], []}, [order: 1], 6, [],
    [
      {:xmlText, [brokerTicketId: 6, order: 1], 1, [],
       '169855177', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 7, [], '\n    ', :text},
   {:xmlElement, :section, :section, [], {:xmlNamespace, [], []},
    [order: 1], 8, [],
    [{:xmlText, [section: 8, order: 1], 1, [], 'SEC1', :text}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 9, [], '\n    ', :text},
   {:xmlElement, :row, :row, [], {:xmlNamespace, [], []},
    [order: 1], 10, [],
    [{:xmlText, [row: 10, order: 1], 1, [], 'N', :text}], [],
    :undefined, :undeclared},
   {:xmlText, [order: 1], 11, [], '\n    ', :text},
   {:xmlElement, :seats, :seats, [], {:xmlNamespace, [], []},
    [order: 1], 12, [], [], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 13, [], '\n    ', :text},
   {:xmlElement, :notes, :notes, [], {:xmlNamespace, [], []},
    [order: 1], 14, [],
    [
      {:xmlText, [notes: 14, order: 1], 1, [],
       'Limited view. Please note that you will need to use an iOS or Android mobile device to gain entry to your event.',
       :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 15, [], '\n    ', :text},
   {:xmlElement, :quantity, :quantity, [], 
    {:xmlNamespace, [], []}, [order: 1], 16, [],
    [{:xmlText, [quantity: 16, order: 1], 1, [], '2', :text}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 17, [], '\n    ', :text},
   {:xmlElement, :cost, :cost, [], {:xmlNamespace, [], []},
    [order: 1], 18, [],
    [{:xmlText, [cost: 18, order: 1], 1, [], '324.00', :text}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 19, [], '\n    ', :text},
   {:xmlElement, :event, :event, [], {:xmlNamespace, [], []},
    [order: 1], 20, [],
    [
      {:xmlText, [event: 20, order: 1], 1, [],
       'Dave Matthews Band (Rescheduled from 7/17/2020, 7/16/2021)',
       :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 21, [], '\n    ', :text},
   {:xmlElement, :eventDate, :eventDate, [],
    {:xmlNamespace, [], []}, [order: 1], 22, [],
    [
      {:xmlText, [eventDate: 22, order: 1], 1, [],
       '2021-08-20 19:30:00', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 23, [], '\n    ', :text},
   {:xmlElement, :orderDate, :orderDate, [],
    {:xmlNamespace, [], []}, [order: 1], 24, [],
    [
      {:xmlText, [orderDate: 24, order: 1], 1, [],
       '2021-06-18 05:43:13', :text}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 25, [], '\n    ', :text},
   {:xmlElement, :expectedShipDate, :expectedShipDate, [],
    {:xmlNamespace, [], []}, [order: 1], 26, [],
    [
      {:xmlText, [expectedShipDate: 26, order: 1], 1, [],
       '2021-06-18 00:00:00', ...}
    ], [], :undefined, :undeclared},
   {:xmlText, [order: 1], 27, [], '\n    ', :text},
   {:xmlElement, :venue, :venue, [], {:xmlNamespace, [], []},
    [order: 1], 28, [], [{:xmlText, [venue: 28, ...], 1, ...}],
    [], :undefined, :undeclared},
   {:xmlText, [order: 1], 29, [], '\n    ', :text},
   {:xmlElement, :status, :status, [], {:xmlNamespace, [], []},
    [order: 1], 30, [], [{:xmlText, ...}], [], :undefined, ...},
   {:xmlText, [order: 1], 31, [], '\n    ', :text},
   {:xmlElement, :purchaseOrderId, :purchaseOrderId, [],
    {:xmlNamespace, [], []}, [order: 1], 32, [], [...], ...},
   {:xmlText, [order: 1], 33, [], '\n    ', :text},
   {:xmlElement, :electronicDelivery, :electronicDelivery, [],
    {:xmlNamespace, [], ...}, [order: 1], 34, ...},
   {:xmlText, [order: 1], 35, [], '\n    ', :text},
   {:xmlElement, :passThrough, :passThrough, [], {...}, ...},
   {:xmlText, [order: 1], 37, [], ...},
   {:xmlElement, :listingId, :listingId, ...},
   {:xmlText, [...], ...},
   {:xmlElement, ...},
   {...},
   ...
 ], [], '/Users/sohaibanwar/Documents/elixir_project/tac4',
 :undeclared}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM