Skip to content

Latest commit

 

History

History
133 lines (99 loc) · 2.61 KB

File metadata and controls

133 lines (99 loc) · 2.61 KB

Getting Started

Installation

Add simdxml to your mix.exs dependencies:

Mix.install([{:simdxml, "~> 0.1.0"}])

Precompiled NIF binaries are available for macOS (Apple Silicon, Intel), Linux (x86_64, aarch64, musl), and Windows. If a precompiled binary is not available for your platform, set SIMDXML_BUILD=1 to compile from source (requires Rust toolchain).

Parsing XML

xml = """
<library>
  <book lang="en">
    <title>Elixir in Action</title>
    <author>Sasa Juric</author>
  </book>
  <book lang="ja">
    <title>Programming Elixir</title>
    <author>Dave Thomas</author>
  </book>
</library>
"""

doc = SimdXml.parse!(xml)

The returned %SimdXml.Document{} is an opaque, immutable reference to a Rust-side structural index. The index uses ~16 bytes per XML tag (vs ~35 for a typical DOM), and the original XML bytes remain on the Rust side.

Querying with XPath

# Direct child text of matching elements
SimdXml.xpath_text!(doc, "//title")
# All descendant text (XPath string-value)
SimdXml.xpath_string!(doc, "//book")
# With predicates
SimdXml.xpath_text!(doc, "//book[@lang='en']/title")

Every function has both ok/error and ! (bang) variants:

{:ok, titles} = SimdXml.xpath_text(doc, "//title")
titles

Navigating Elements

root = SimdXml.Document.root(doc)
root.tag
# Elements implement Enumerable -- iterate over children
Enum.map(root, & &1.tag)
# Access attributes
[book | _] = SimdXml.Element.children(root)

%{
  lang: SimdXml.Element.get(book, "lang"),
  attributes: SimdXml.Element.attributes(book),
  parent_tag: SimdXml.Element.parent(book).tag
}
# Context-sensitive XPath
SimdXml.Element.xpath_text(book, "./title")

Compiled Queries

When querying many documents with the same expression, compile it once:

query = SimdXml.compile!("//title")

doc1 = SimdXml.parse!("<r><title>First</title></r>")
doc2 = SimdXml.parse!("<r><title>Second</title></r>")

{SimdXml.eval_text!(doc1, query), SimdXml.eval_text!(doc2, query)}
# Optimized operations
{SimdXml.eval_count!(doc, query), SimdXml.eval_exists?(doc, query)}

Result Helpers

SimdXml.Result.all(doc, "//title")
SimdXml.Result.one(doc, "//title")
SimdXml.Result.fetch(doc, "//title")
SimdXml.Result.fetch(doc, "//missing")

Next Steps