# `Yog.IO.GraphML`
[🔗](https://github.com/code-shoily/yog_ex/blob/v1.0.0/lib/yog/io/graphml.ex#L1)

GraphML (Graph Markup Language) serialization support.

Provides functions to serialize and deserialize graphs in the GraphML format,
an XML-based format widely supported by graph visualization and analysis tools
like Gephi, yEd, Cytoscape, and NetworkX.

## Format Overview

GraphML is an XML-based format that supports:
- **Nodes** with custom attributes
- **Edges** with custom attributes
- **Directed and undirected** graphs
- **Hierarchical graphs** (not yet supported)

## Performance

For optimal performance with large GraphML files, add the optional `saxy`
dependency to your project:

    {:saxy, "~> 1.5"}

When available, `saxy` provides a fast streaming SAX parser that significantly
improves loading times:
- **Without saxy:** Uses Erlang's `:xmerl` (DOM parser, slower for large files)
- **With saxy:** Uses streaming parser (up to 3-4x faster for large files)

## Examples

### Basic Serialization and Deserialization

    iex> graph = Yog.directed()
    ...> |> Yog.add_node(1, "Alice")
    ...> |> Yog.add_node(2, "Bob")
    ...> |> Yog.add_edge_ensure(from: 1, to: 2, with: "friend")
    iex> xml = Yog.IO.GraphML.serialize(graph)
    iex> String.contains?(xml, "Alice")
    true
    iex> String.contains?(xml, "Bob")
    true

### Custom Attributes with Type Information

    iex> graph = Yog.directed()
    ...> |> Yog.add_node(1, %{name: "Alice", age: 30})
    ...> |> Yog.add_node(2, %{name: "Bob", age: 25})
    ...> |> Yog.add_edge_ensure(from: 1, to: 2, with: %{weight: 5, relation: "friend"})
    iex> node_attr = fn data ->
    ...>   %{"label" => data.name, "age" => Integer.to_string(data.age)}
    ...> end
    iex> edge_attr = fn data ->
    ...>   %{"weight" => Integer.to_string(data.weight), "type" => data.relation}
    ...> end
    iex> xml = Yog.IO.GraphML.serialize_with(node_attr, edge_attr, graph)
    iex> String.contains?(xml, "Alice")
    true

### Reading from File

    # Read a GraphML file from disk
    {:ok, graph} = Yog.IO.GraphML.read("network.graphml")

### Writing to File

    # Write with default string conversion
    Yog.IO.GraphML.write("output.graphml", graph)

# `default_options`

```elixir
@spec default_options() :: tuple()
```

Returns default GraphML serialization options.

Time complexity: $\mathcal{O}(1)$

# `deserialize`

```elixir
@spec deserialize(String.t()) :: {:ok, Yog.graph()} | {:error, term()}
```

Deserializes a GraphML string to a graph using default conversion.

Raises `ArgumentError` if xml is not a binary string.

Time complexity: $\mathcal{O}(V + E)$

# `deserialize_with`

```elixir
@spec deserialize_with((map() -&gt; any()), (map() -&gt; any()), String.t()) ::
  {:ok, Yog.graph()} | {:error, term()}
```

Deserializes a GraphML string into a graph with custom data mappers.

Raises `ArgumentError` if xml or data mappers are invalid.

Time complexity: $\mathcal{O}(V + E)$

# `options_with`

```elixir
@spec options_with(non_neg_integer(), boolean(), keyword()) :: tuple()
```

Creates GraphML options with custom formatting.

Raises `ArgumentError` if parameters are invalid.

Time complexity: $\mathcal{O}(1)$

# `read`

```elixir
@spec read(String.t()) :: {:ok, Yog.graph()} | {:error, term()}
```

Reads a graph from a GraphML file using default conversion.

Raises `ArgumentError` if path is not a binary string.

Time complexity: $\mathcal{O}(V + E)$ + file I/O

# `read_with`

```elixir
@spec read_with(String.t(), (map() -&gt; any()), (map() -&gt; any())) ::
  {:ok, Yog.graph()} | {:error, term()}
```

Reads a graph from a GraphML file with custom data mappers.

Raises `ArgumentError` if path is not a binary string or mappers are invalid.

Time complexity: $\mathcal{O}(V + E)$ + file I/O

# `serialize`

```elixir
@spec serialize(Yog.graph() | Yog.DAG.t()) :: String.t()
```

Serializes a graph to GraphML string using default attribute conversion.

Raises `ArgumentError` if graph is invalid.

Time complexity: $\mathcal{O}(V + E)$

# `serialize_with`

```elixir
@spec serialize_with((any() -&gt; map()), (any() -&gt; map()), Yog.graph() | Yog.DAG.t()) ::
  String.t()
```

Serializes a graph to GraphML string with custom attribute mappers.

Raises `ArgumentError` if mappers or graph are invalid.

Time complexity: $\mathcal{O}(V + E)$

# `serialize_with_options`

```elixir
@spec serialize_with_options(
  (any() -&gt; map()),
  (any() -&gt; map()),
  tuple(),
  Yog.graph() | Yog.DAG.t()
) ::
  String.t()
```

Serializes a graph to a GraphML string with custom options.

Raises `ArgumentError` if arguments or options are invalid.

Time complexity: $\mathcal{O}(V + E)$

# `serialize_with_types`

```elixir
@spec serialize_with_types(
  (any() -&gt; map()),
  (any() -&gt; map()),
  Yog.graph() | Yog.DAG.t()
) :: String.t()
```

Serializes a graph to GraphML with typed attributes for Gephi compatibility.

Raises `ArgumentError` if mappers or graph are invalid.

Time complexity: $\mathcal{O}(V + E)$

# `serialize_with_types_and_options`

```elixir
@spec serialize_with_types_and_options(
  (any() -&gt; map()),
  (any() -&gt; map()),
  tuple(),
  Yog.graph() | Yog.DAG.t()
) :: String.t()
```

Serializes a graph to GraphML with typed attributes and custom options.

Raises `ArgumentError` if arguments or options are invalid.

Time complexity: $\mathcal{O}(V + E)$

# `write`

```elixir
@spec write(String.t(), Yog.graph() | Yog.DAG.t()) :: {:ok, nil} | {:error, atom()}
```

Writes a graph to a GraphML file using default attribute conversion.

Raises `ArgumentError` if path is not a binary string or graph is invalid.

Time complexity: $\mathcal{O}(V + E)$ + file I/O

# `write_with`

```elixir
@spec write_with(
  String.t(),
  (any() -&gt; map()),
  (any() -&gt; map()),
  Yog.graph() | Yog.DAG.t()
) ::
  {:ok, nil} | {:error, atom()}
```

Writes a graph to a GraphML file with custom attribute mappers.

Raises `ArgumentError` if path is not a binary string or graph/mappers are invalid.

Time complexity: $\mathcal{O}(V + E)$ + file I/O

# `write_with_types`

```elixir
@spec write_with_types(
  String.t(),
  (any() -&gt; map()),
  (any() -&gt; map()),
  Yog.graph() | Yog.DAG.t()
) ::
  {:ok, nil} | {:error, atom()}
```

Writes a graph to a GraphML file with typed attributes for Gephi compatibility.

Raises `ArgumentError` if path is not a binary string or graph/mappers are invalid.

Time complexity: $\mathcal{O}(V + E)$ + file I/O

---

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