1   Description

XmlElixirStructs builds on top of SweetXml. SweetXml is a layer on top of Xmerl. XmlElixirStructs converts the Xmerl records in a parsed document produced by SweetXml into Elixir structs.

This document describes XmlElixirStructs that can be found here: https://github.com/dkuhlman/xmlelixirstructs.

For information about SweetXml see: https://hexdocs.pm/sweet_xml/SweetXml.html.

One benefit of this capability is that tab completion on structs works in iex. For example, after parsing and converting an XML document to Elixir structs, type "element." and then press TAB to see a list of the fields in an element.

2   Installation

XmlElixirStructs is intended to be used as part of an Elixir Mix project.

Create an Elixir Mix application by running the following in a directory where you want to create your application:

$ mix new myapp

Add xmlelixirstructs to your mix project by adding the following to your mix.exs file under deps:

def deps do
  [
    {:xmlelixirstructs, github: "dkuhlman/xmlelixirstructs"},
  ]
end

Then do:

$ cd myapp
$ mix deps.get
$ mix deps.compile
$ mix compile
$ iex -S mix
iex> element = Xmlstruct.Utils.convert("path/to/document.xml")
iex> IO.puts("element tag #{element.name")

3   Guidance

Where to find stuff:

  • The XML struct definitions are in lib/xmlstructlib.ex.
  • That file also implements module Xmlstruct.Conversions, which contains functions (convert_*) that convert individual Xmerl record types.
  • A variety of helper functions and utilities are in module Xmlstruct.Utils in lib/xmlstructlib.ex. In iex, you can type "h Xmlstruct.Utils.some_func" to get help on most of the helper functions in Xmlstruct.Utils.

4   Examples

Convert an XML document to Elixir structs:

ex(4)> element = Xmlstruct.Utils.convert("path/to/xml/document.xml")

Convert an XML document in a string to Elixir structs:

iex> text = File.read!("path/to/document.xml")
iex> element = Xmlstruct.Utils.convert_string(text)
iex> IO.puts(element.name)

SweetXml provides support for XPath. XmlElixirStructs does not. You can work around this by using the capabilities of both SweetXml and XmlElixirStructs. First create the SweetXml Xmerl record structure, then use SweetXml.xpath to search for an element, and then convert that Xmerl record to an Elixir Struct using XmlElixirStructs. Here is an example:

iex> import SweetXml
iex> rec = File.stream!("path/to/document.xml") |> SweetXml.parse
iex> rec1 = SweetXml.xpath(rec, ~x".//some-element-name")
iex> element = Xmlstruct.Utils.convert(rec1)
iex> IO.puts(element.name)

And another example:

path = "path/to/document.xml"
pattern = ~x".//bbb|ddd"l
File.stream!(path)
|> SweetXml.parse
|> SweetXml.xpath(pattern)
|> Enum.map(&Xmlstruct.Utils.convert/1)
|> Enum.each(fn el -> IO.puts(el.name) end)

Show (print) (1) the name of an element, (2) the name an value of its attributes, and (3) its immediate children/contents (the names of immediate child elements and the values of immediate text children):

def show_element(element) do
  IO.puts("element name: #{element.name}")
  Enum.each(element.attributes, fn (attr) ->
    IO.puts("attribute -- name: #{attr.name}  value: #{attr.value}")
  end)
  Enum.each(element.content, fn (item) ->
    case item do
      %Xmlstruct.Element{} ->
        IO.puts("    child -- name: #{item.name}")
      %Xmlstruct.Text{} ->
        IO.puts("    text -- value: #{item.value}")
      _ -> nil
    end
    IO.puts("----")
  end)
end

Notes:

  • The above example shows how to match against the type of an item by matching against its Struct, for example, %Xmlstruct.Element{}

Published

Category

elixir

Tags

Contact