View Source XmlSchema (XmlSchema v1.3.0)
Adds XML parsing and generation to modules via use XmlSchema
.
Define Xml structures with:
Options to use
:
tag: <string>
string to use as xml tag name for this element.
This allows a tag name not derived from the module name.
print: <boolean>
will print the macro generated code, e.g:
`print: Mix.env() in [:test, :dev]`
Generated functions
An XmlSchema will provide the generated functions:
- parse_xml/1 - accepts an xml string to parse
- xml_tag/0 - returns the tag used when generating xml from this node
- xml_tag_list - order list of tags in this schema
- transform/1 - overridable function that can be used to transform tag names during parsing
Example
defmodule Simple do
use XmlSchema, xml_name: "a"
xml do
xml_tag :x, :string
xml_tag :y, :boolean
xml_one :z, Z do
xml_tag :a, :string
xml_tag :b, :string
end
xml_many :j, J do
xml_tag :q, :string
end
xml_tag :g, {:array, :string}
end
end
Will parse
<?xml encoding="utf-8" ?>
<a someattr="blue" otherattr="red">
<x>hill</x>
<y>false</y>
<z>
<a>tree</a>
<b>bush</b>
</z>
<j>
<q>cat</q>
</j>
<j>
<q>dog</q>
</j>
<g>hippo</g>
<g>elephant</g>
<g>rhino</g>
</a>
Into:
%Simple{
_attributes: %{"otherattr" => "red", "someattr" => "blue"},
x: "hill",
y: false,
z: %Simple.Z{_attributes: nil, a: "tree", b: "bush"},
j: [
%Simple.J{_attributes: nil, q: "cat"},
%Simple.J{_attributes: nil, q: "dog"}
],
g: ["hippo", "elephant", "rhino"]
}
Attributes
Parsed attibutes are stored in a map, this precludes multiple same named attribute in a single tag. It also does not preserve attribute ordering.
Terminal nodes defined with xml_tag
provide bare values. If you wish to
capture attributes the type argument takes the form of {:param, type}
which
will result in not bare values but a tuple of {value, %{attribute map}}
.
An example:
defmodule Example.Attribute do
use XmlSchema, tag: "a"
xml do
xml_tag :k, :string
xml_tag :j, {:param, :string}
xml_tag :manyj, {:array, {:param, :string}}
end
def doc do
"""
<a first="lemon" second="lime">
<k third="peach">one</k>
<j fourth="orange">tree</j>
<manyj five="cherry">shrub</manyj>
<manyj six="berry">flower</manyj>
</a>
"""
end
def expect do
%Example.Attribute{
_attributes: %{"first" => "lemon", "second" => "lime"},
k: "one",
j: {"tree", %{"fourth" => "orange"}},
manyj: [
{"shrub", %{"five" => "cherry"}},
{"flower", %{"six" => "berry"}}
]
}
end
def expect_xml do
"""
<?xml version="1.0" encoding="UTF-8"?>
<a first="lemon" second="lime">
<k>one</k>
<j fourth="orange">tree</j>
<manyj five="cherry">shrub</manyj>
<manyj six="berry">flower</manyj>
</a>
"""
|> String.trim_trailing()
end
end
For more examples, see test/support.
Summary
Functions
Generate xml document from xml schema
Generate xml document from xml schema with name
top tag
Parse an xml string based on the structure of module
, which must be an
XmlSchema. This function is added to any module that uses XmlSchema and
is simplest to call the function there instead of this one.
Start definition of xml document structure.
Similar to xml_one/3
except the tag can occur 0 or
more times. Values will be presented in a list. Unlike xml_one
if
the tag is not present an empty list will result.
Declare a tag that occurs once with XML tag name
as either
a block or a declared module. Modules generated by blocks automatically
use XmlSchema
. nil value is used if a tag is not present.
Declare an XML tag with a scalar value with type conversion. Any type accepted by Ecto.Schema can be used. Custom types can be defined in the same manner. An xml_tag is terminal, for tags containing substructure use xml_one or xml_many. See attributes section above for details on how to capture tag attributes.
Functions
Generate xml document from xml schema
Generate xml document from xml schema with name
top tag
Parse an xml string based on the structure of module
, which must be an
XmlSchema. This function is added to any module that uses XmlSchema and
is simplest to call the function there instead of this one.
Start definition of xml document structure.
Similar to xml_one/3
except the tag can occur 0 or
more times. Values will be presented in a list. Unlike xml_one
if
the tag is not present an empty list will result.
In this example (from test/support/example/many.ex),
doc
is an xml sample that will result in the expect
struct.
defmodule Example.Many do
use XmlSchema, tag: "a"
xml do
xml_many :j, Example.Tag
xml_many :s, Example.Tag
end
def doc do
"""
<a>
<j>
<k>one</k>
</j>
<j>
<k>two</k>
</j>
</a>
"""
end
def expect do
%Example.Many{
_attributes: nil,
j: [
%Example.Tag{_attributes: nil, k: "one"},
%Example.Tag{_attributes: nil, k: "two"}
],
s: []
}
end
def expect_xml do
"""
<?xml version="1.0" encoding="UTF-8"?>
<a>
<j>
<k>one</k>
</j>
<j>
<k>two</k>
</j>
</a>
"""
|> String.trim_trailing()
end
end
Declare a tag that occurs once with XML tag name
as either
a block or a declared module. Modules generated by blocks automatically
use XmlSchema
. nil value is used if a tag is not present.
Block form example:
defmodule Example.OneBlock do
use XmlSchema, tag: "a"
xml do
xml_one :j, Tag do
xml_tag :k, :string
end
end
def doc do
"""
<a>
<j>
<k>one</k>
</j>
</a>
"""
end
def expect do
%Example.OneBlock{
_attributes: nil,
j: %Example.OneBlock.Tag{_attributes: nil, k: "one"}
}
end
def expect_xml do
"""
<?xml version="1.0" encoding="UTF-8"?>
<a>
<j>
<k>one</k>
</j>
</a>
"""
|> String.trim_trailing()
end
end
In this example (from test/support/example/one.ex)
doc
is an xml sample that will result in the expect
struct.
Defined module form:
defmodule Example.One do
use XmlSchema, tag: "a"
xml do
xml_one :j, Example.Tag
xml_one :s, Example.Tag
end
def doc do
"""
<a>
<j>
<k>one</k>
</j>
</a>
"""
end
def expect do
%Example.One{
_attributes: nil,
j: %Example.Tag{_attributes: nil, k: "one"},
s: nil
}
end
def expect_xml do
"""
<?xml version="1.0" encoding="UTF-8"?>
<a>
<j>
<k>one</k>
</j>
</a>
"""
|> String.trim_trailing()
end
end
Depends on the definition of module Example.Tag
.
Declare an XML tag with a scalar value with type conversion. Any type accepted by Ecto.Schema can be used. Custom types can be defined in the same manner. An xml_tag is terminal, for tags containing substructure use xml_one or xml_many. See attributes section above for details on how to capture tag attributes.
defmodule Example.Tag do
use XmlSchema, tag: "a"
xml do
xml_tag :k, :string
end
def doc do
"""
<a>
<k>one</k>
</a>
"""
end
def expect do
%Example.Tag{_attributes: nil, k: "one"}
end
def expect_xml do
"""
<?xml version="1.0" encoding="UTF-8"?>
<a>
<k>one</k>
</a>
"""
|> String.trim_trailing()
end
end