SimpleXml.XmlNode (simple_xml v0.1.1)

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

Assume that the following XML has been parsed.
```
  <foo a="1" b="2"></foo>
```

iex> SimpleXml.XmlNode.attribute({"foo", [{"a", 1}, "b", 2], []}, "a")
{:ok, 1}

### Returns the first matching attribute it finds

Assume that the following XML has been parsed.
```
  <foo a="1" a="2"></foo>
```

iex> SimpleXml.XmlNode.attribute({"foo", [{"a", 1}, "a", 2], []}, "a")
{:ok, 1}

### Generates an error when the attribute is missing

Assume that the following XML has been parsed.
```
  <foo a="1" b="2"></foo>
```
iex> SimpleXml.XmlNode.attribute({"foo", [{"a", 1}, "b", 2], []}, "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.

Assume that the following XML has been parsed.
```
  <foo><bar>1</bar><baz>2</baz></foo>
```

iex> SimpleXml.XmlNode.first_child({"foo", [], [{"bar", [], ["1"]}, {"baz", [], ["2"]}]}, "bar")
{:ok, {"bar", [], ["1"]}}

### Returns the first matching node it finds

Assume that the following XML has been parsed.
```
  <foo><bar>1</bar><bar>2</bar></foo>
```

iex> SimpleXml.XmlNode.first_child({"foo", [], [{"bar", [], ["1"]}, {"bar", [], ["2"]}]}, "bar")
{:ok, {"bar", [], ["1"]}}

### Ignores case when matching tag name

Assume that the following XML has been parsed.
```
  <foo><bar>1</bar><bar>2</bar></foo>
```

iex> SimpleXml.XmlNode.first_child({"foo", [], [{"bar", [], ["1"]}, {"bar", [], ["2"]}]}, "BAR")
{:ok, {"bar", [], ["1"]}}

### Wildcard ignores tag namespace

Assume that the following XML has been parsed.
```
  <ns:foo><xs:bar>1</xs:bar><xs:bar>2</xs:bar></ns:foo>
```

iex> SimpleXml.XmlNode.first_child({"ns:foo", [], [{"xs:bar", [], ["1"]}, {"xs:bar", [], ["2"]}]}, "*:bar")
{:ok, {"xs:bar", [], ["1"]}}

### Use Regex to find a child

Assume that the following XML has been parsed.
```
  <ns:foo><xs:bar>1</xs:bar><xs:bar>2</xs:bar></ns:foo>
```

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

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

Assume that the following XML has been parsed.
```
  <foo><bar>1</bar></foo>
```
iex> SimpleXml.XmlNode.first_child({"foo", [], [{"bar", [], ["1"]}]}, "baz")
{:error, {:child_not_found, "baz"}}
@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.

Assume that the following XML has been parsed.
```
  <foo>bar</foo>
```

iex> SimpleXml.XmlNode.text({"foo", [], ["bar"]})
{:ok, "bar"}

### Generates an error when the tag contains no text

Assume that the following XML has been parsed.
```
  <foo><bar>1</bar></foo>
```
iex> SimpleXml.XmlNode.text({"foo", [], [{"bar", [], ["1"]}]})
{:error, {:text_not_found, [{"bar", [], ["1"]}]}}