/libxml

Thin wrapper for Libxml2 using NIF by Elixir

Primary LanguageElixirMIT LicenseMIT

Libxml

Thin wrapper for Libxml2 using NIF

NIF

NIF for Libxml2 are defined in Libxml.Nif.

These functions are thin wrapper. You should manage yourself the memory allocation and deallocation.

For example, Libxml.Nif.xml_read_memory/1 corresponds to xmlReadMemory in Libxml2. xmlReadMemory returns xmlDocPtr pointer. Libxml.Nif.xml_read_memory/1 returns the pointer value as integer.

If you want to see inside the xmlDocPtr pointer, call Libxml.Nif.get_xml_node/1. If you want to apply a value to xmlDocPtr, call Libxml.Nif.set_xml_node/2.

content = "<doc></doc>"
{:ok, docptr} = Libxml.Nif.xml_read_memory(content)
{:ok, docvalue} = Libxml.Nif.get_xml_node(docptr)
#IO.inspect docvalue
# output:
#   %{children: 140639374148016, doc: 140639374150976, last: 140639374148016,
#      name: 0, next: 0, parent: 0, prev: 0, private: 0, type: 9}
assert docvalue.type == 9 # XML_DOCUMENT_NODE

# update
docvalue = %{docvalue | private: 100}
:ok = Libxml.Nif.set_xml_node(docptr, docvalue) # apply

# check
{:ok, docvalue} = Libxml.Nif.get_xml_node(docptr)
assert docvalue.private == 100

# free a doc node
Libxml.Nif.xml_free_doc(docptr)

Typed Thin Wrapper

NIF is incovinient, so this library provides typed thin wrapper.

For example, Libxml.read_memory/1 corresponds to xmlReadMemory in Libxml2. Libxml.read_memory/1 returns a value type of %Libxml.Node{}. %Libxml.Node{} has :pointer field. The pointer value returned the function is assined this field.

If you want to see inside the xmlDocPtr pointer, call Libxml.Node.extract/1. If you want to apply a value to xmlDocPtr, call Libxml.Node.apply/1.

content = "<doc></doc>"
node = %Libxml.Node{} = Libxml.read_memory(content)
node = Libxml.Node.extract(node)
#IO.inspect node
# output:
#   %Libxml.Node{children: %Libxml.Node{children: nil, doc: nil, last: nil,
#     more: nil, name: nil, next: nil, parent: nil, pointer: 140551835942432,
#     prev: nil, private: nil, type: nil},
#    doc: %Libxml.Node{children: nil, doc: nil, last: nil, more: nil, name: nil,
#     next: nil, parent: nil, pointer: 140551835942128, prev: nil, private: nil,
#     type: nil},
#    last: %Libxml.Node{children: nil, doc: nil, last: nil, more: nil, name: nil,
#     next: nil, parent: nil, pointer: 140551835942432, prev: nil, private: nil,
#     type: nil}, more: %Libxml.Node.TODO{}, name: nil, next: nil, parent: nil,
#    pointer: 140551835942128, prev: nil, private: 0, type: :document_node}
assert node.type == :document_node

# update
node = %{node | private: 100}
:ok = Libxml.Node.apply(node) # apply

# check
node = Libxml.Node.extract(node)
assert node.private == 100

# free a doc node
Libxml.free_doc(node)