SimpleXml.XmlNode (simple_xml v0.1.2)

A simplistic XML node representation that uses the saxy lib, in order to avoid xmerl based libraries, which have the vulnerability that they create new atoms for each tag within the XML document.

For simplicity, this module ignores namespaces within the document.

Summary

Functions

Obtains value for the given attribute.

Obtains the first child of the given node with the given string tag name via case-insensitive match.

Obtains text within the body of a tag.

Types

@type xml_node() :: SimpleXml.xml_node()

Functions

Link to this function

attribute(arg, attr_name)

@spec attribute(xml_node(), String.t()) :: {:ok, String.t()} | {:error, any()}

Obtains value for the given attribute.

Examples

Obtains the value for an attribute

iex> {:ok, node} = SimpleXml.parse(~s'<foo a="1" b="2"></foo>')
iex> SimpleXml.XmlNode.attribute(node, "a")
{:ok, "1"}

Returns the first matching attribute it finds

iex> {:ok, node} = SimpleXml.parse(~s'<foo a="1" a="2"></foo>')
iex> SimpleXml.XmlNode.attribute(node, "a")
{:ok, "1"}

Generates an error when the attribute is missing

iex> {:ok, node} = SimpleXml.parse(~s'<foo a="1" b="2"></foo>')
iex> SimpleXml.XmlNode.attribute(node, "c")
{:error, {:attribute_not_found, "c"}}
Link to this function

first_child(xml_node, child_name)

@spec first_child(xml_node(), String.t() | Regex.t()) ::
  {:ok, xml_node()} | {:error, any()}

Obtains the first child of the given node with the given string tag name via case-insensitive match.

Use a *: prefix for the tag name to ignore namespace associated with the tag name.

Alternatively, you can supply a regex to pattern match the child name. When Regex is supplied the Regex's case sensitivity is respected.

Examples

Obtains the first child by the given name

iex> {:ok, node} = SimpleXml.parse(~s'<foo><bar>1</bar><baz>2</baz></foo>')
iex> SimpleXml.XmlNode.first_child(node, "bar")
{:ok, {"bar", [], ["1"]}}

Returns the first matching node it finds

iex> {:ok, node} = SimpleXml.parse(~s'<foo><bar>1</bar><bar>2</bar></foo>')
iex> SimpleXml.XmlNode.first_child(node, "bar")
{:ok, {"bar", [], ["1"]}}

Ignores case when matching tag name

iex> {:ok, node} = SimpleXml.parse(~s'<foo><bar>1</bar><bar>2</bar></foo>')
iex> SimpleXml.XmlNode.first_child(node, "BAR")
{:ok, {"bar", [], ["1"]}}

Wildcard ignores tag namespace

iex> {:ok, node} = SimpleXml.parse(~s'<ns:foo><xs:bar>1</xs:bar><xs:bar>2</xs:bar></ns:foo>')
iex> SimpleXml.XmlNode.first_child(node, "*:bar")
{:ok, {"xs:bar", [], ["1"]}}

Use Regex to find a child

iex> {:ok, node} = SimpleXml.parse(~s'<ns:foo><xs:bar>1</xs:bar><xs:bar>2</xs:bar></ns:foo>')
iex> SimpleXml.XmlNode.first_child(node, ~r/.*:BAR/i)
{:ok, {"xs:bar", [], ["1"]}}

Generates an error when there's no child with the given name

iex> {:ok, node} = SimpleXml.parse(~s'<foo><bar>1</bar></foo>')
iex> SimpleXml.XmlNode.first_child(node, "baz")
{:error, {:child_not_found, [child_name: "baz", actual_children: [{"bar", [], ["1"]}]]}}
@spec text(xml_node()) :: {:ok, xml_node()} | {:error, any()}

Obtains text within the body of a tag.

Examples

Obtains the text contents of a tag

iex> {:ok, node} = SimpleXml.parse(~s'<foo>bar</foo>')
iex> SimpleXml.XmlNode.text(node)
{:ok, "bar"}

Generates an error when the tag contains no text

iex> {:ok, node} = SimpleXml.parse(~s'<foo><bar>1</bar></foo>')
iex> SimpleXml.XmlNode.text(node)
{:error, {:text_not_found, [{"bar", [], ["1"]}]}}