# `Dmn.XML.Element`
[🔗](https://github.com/FeeJai/BDM/blob/dmn-v0.1.0/apps/dmn/lib/dmn/xml/element.ex#L1)

An element of an XML document, as `Dmn.XML` reads it.

Names are strings and nothing is an atom: the document is not trusted, and an atom is never freed. The namespace of the
element and of its attributes is resolved, so the reader of the model asks for `{namespace, "decision"}` and not for a
prefix.

| Field | Is |
| ----- | -- |
| `namespace` | the URI of the namespace of the element, `nil` for none |
| `name` | the local name |
| `attributes` | the attributes that have no namespace, by name |
| `qualified` | the attributes that have one, by `{namespace, name}` (`xsi:type`, and the attributes of other vocabularies) |
| `namespaces` | the prefixes that the element declares itself, by prefix (`""` for the default namespace); those in scope at it are the ones of its ancestors too (`enter/2`, `resolve/2`) |
| `children` | the child elements, in order |
| `text` | the character data directly inside the element, in one string: white space only when the element has child elements and nothing else |
| `line` | the line of the start tag |

# `scope`

```elixir
@type scope() :: [%{optional(String.t()) =&gt; String.t()}]
```

The prefixes in scope at an element: the declarations of the element and of each of its ancestors, the innermost first. An element
has only its own (`namespaces`), so a deep document costs what it declares and not what is in scope at each of its leaves.

# `t`

```elixir
@type t() :: %Dmn.XML.Element{
  attributes: %{optional(String.t()) =&gt; String.t()},
  children: [t()],
  line: pos_integer() | nil,
  name: String.t(),
  namespace: String.t() | nil,
  namespaces: %{optional(String.t()) =&gt; String.t()},
  qualified: %{optional({String.t(), String.t()}) =&gt; String.t()},
  text: String.t()
}
```

# `attribute`

```elixir
@spec attribute(t(), String.t()) :: String.t() | nil
```

The value of an attribute that has no namespace, or `nil`.

    iex> Dmn.XML.Element.attribute(%Dmn.XML.Element{name: "a", attributes: %{"id" => "x"}}, "id")
    "x"

# `children`

```elixir
@spec children(t(), String.t() | nil, String.t()) :: [t()]
```

The child elements with this local name and namespace.

    iex> element = %Dmn.XML.Element{name: "a", children: [%Dmn.XML.Element{name: "b", namespace: "urn:x"}, %Dmn.XML.Element{name: "c"}]}
    iex> Enum.map(Dmn.XML.Element.children(element, "urn:x", "b"), & &1.name)
    ["b"]

# `enter`

```elixir
@spec enter(scope(), t()) :: scope()
```

The scope at an element, given the scope at its parent: its own declarations go in front of those of its ancestors.

    iex> parent = Dmn.XML.Element.root_scope()
    iex> child = %Dmn.XML.Element{name: "a", namespaces: %{"p" => "urn:p"}}
    iex> Dmn.XML.Element.enter(parent, child)
    [%{"p" => "urn:p"}, %{"xml" => "http://www.w3.org/XML/1998/namespace"}]

# `resolve`

```elixir
@spec resolve(scope(), String.t()) :: {:ok, {String.t() | nil, String.t()}} | :error
```

Resolves a name with a prefix (`"feel:string"`) to `{namespace, local name}`, with the prefixes in scope. A name with no prefix is
in the default namespace, if there is one. `:error` for a prefix that is not declared.

    iex> scope = Dmn.XML.Element.enter([%{"q" => "urn:outer", "p" => "urn:old"}], %Dmn.XML.Element{name: "a", namespaces: %{"p" => "urn:p", "" => "urn:d"}})
    iex> {Dmn.XML.Element.resolve(scope, "p:x"), Dmn.XML.Element.resolve(scope, "y"), Dmn.XML.Element.resolve(scope, "q:z"), Dmn.XML.Element.resolve(scope, "r:z")}
    {{:ok, {"urn:p", "x"}}, {:ok, {"urn:d", "y"}}, {:ok, {"urn:outer", "z"}}, :error}

# `root_scope`

```elixir
@spec root_scope() :: scope()
```

The scope before the root element: the `xml` prefix, which is always declared.

    iex> Dmn.XML.Element.root_scope()
    [%{"xml" => "http://www.w3.org/XML/1998/namespace"}]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
