ExXml (ex_xml v0.2.0)

ExXml allows you to use XML in your library to construct code. This can be helpful if you need to deal more descriptive type of programming like the ones that are already using a SGML or XML languages like HTML and ODF. It also allows you to compose components out of Pascal case XML elements. You can also have a list of elements which are wrapped with a fragment.

Out of the box ExXml sigil ~x() constructs the Element and Fragment structs that you can convert to quoted version of Elixir to create code out of this XML like data. It's as close to JSX as can be done in Elixir.

Examples

Simple syntax with some nesting and a self closing element

~x(
  <foo something=b>
    <bar2 something="a"/>
    <a>
      2
    </a>
  </foo>
)

Now with a fragment

~x(
  <>
    <foo>
      <bar2 something="a"/>
      <a>
        2
      </a>
    </foo>
  </>
)

This allows you to use a module if you want

~x(
  <Foo>
    <bar2 something="a"/>
    <a>2</a>
  </Foo>
)

How do you implement your library with ExXml

You have to include use ExXml in your module then implement either parse_ex_xml function in our library if you want to expose the sigil x syntax or @parse_ex_xml attribute if you want to use the syntax only within your library. You have to return a quoted from of you data. You can look at Elixir Macro documentation for that. Because the sigil syntax is a macro and you are probably using this library to construct something else than just the output of this library.

Summary

Functions

do_sigil_x(arg1, arg2, caller, module)

escape_ex_xml(list)

@spec escape_ex_xml([...]) :: Macro.t()

get_meta_content(arg, acc)

@spec get_meta_content(
  {atom(), [...]},
  map()
) :: map()

list_to_context(list)

@spec list_to_context([...]) :: {binary(), map()}

parse_ex_xml(ex_xml)

@spec parse_ex_xml([...]) ::
  {:ok,
   [
     %ExXml.Element{
       attributes: term(),
       children: term(),
       name: term(),
       type: term()
     }
     | %ExXml.Fragment{attributes: term(), children: term()}
   ]}
  | {:error, String.t()}

parse_xml(binary, opts \\ [])

@spec parse_xml(binary(), keyword()) ::
  {:ok, [term()], rest, context, line, byte_offset}
  | {:error, reason, rest, context, line, byte_offset}
when line: {pos_integer(), byte_offset},
     byte_offset: non_neg_integer(),
     rest: binary(),
     reason: String.t(),
     context: map()

Parses the given binary as parse_xml.

Returns {:ok, [token], rest, context, position, byte_offset} or {:error, reason, rest, context, line, byte_offset} where position describes the location of the parse_xml (start position) as {line, offset_to_start_of_line}.

To column where the error occurred can be inferred from byte_offset - offset_to_start_of_line.

Options

  • :byte_offset - the byte offset for the whole binary, defaults to 0
  • :line - the line and the byte offset into that line, defaults to {1, byte_offset}
  • :context - the initial context value. It will be converted to a map