package
0.0.0-20230623162953-994bc1c10b84
Repository: https://github.com/viant/dm.git
Documentation: pkg.go.dev

# README

##Introduction The package xml of dm works very similar to the html package but for templates in the xml format.

Usage

Similarly to the html in order to manipulate xml, first you need to create VirtualDOM, one can be shared across the app:

template := []byte("<?xml version=...")
dom, err := xml.New(template)
// handle error
bufferSize := xml.BufferSize(1024)
filter := option.NewFilters(
	option.NewFilter("foo", "attr1", "attr2"), 
	option.NewFilter("name", "attr1", "attr2"),
	)
dom, err := xml.New(template, bufferSize, filter)
// handle error

Then you need to create a Document:

document := dom.Document()

Now you can get/set Attribute, get/set Value by using selectors.

elementSelector := xml.Selector{
	Name: "foo",
	Attributes: []AttributeSelector{
		Name: "id", 
		Value: "1",
	}
}

Usage:

	template := `
<?xml version="1.0" encoding="UTF-8"?>
<foo test="true">
    <id>1</id>
    <name>foo name</name>
    <address>
        <street>abc</street>
        <zip-code>123456</zip-code>
        <country>
            <id>1</id>
            <name>def</name>
        </country>
    </address>
    <quantity>123</quantity>
    <price>50.5</price>
    <type>fType</type>
</foo>`

filters := option.NewFilters(
    option.NewFilter("foo", "test"),
    option.NewFilter("id"),
    option.NewFilter("name"),
    option.NewFilter("address"),
)

vdom, err := xml.New(template, filters)
if err != nil {
    fmt.Println(err)
    return
}

dom := vdom.Document()

elem, ok := dom.SelectFirst(xml.Selector{Name: "foo"}, xml.Selector{Name: "id"})
if ok {
    elem.SetValue("10")
}

elem, ok = dom.SelectFirst(xml.Selector{Name: "foo"}, xml.Selector{Name: "address"})
if ok {
    elem.SetValue("")
    elem.AddElement("<new-elem>New element value</new-elem>")
}

elemIt := dom.Select(xml.Selector{Name: "foo", Attributes: []xml.AttributeSelector{{Name: "test", Value: "true"}}})
for elemIt.Has() {
    elem, _ := elemIt.Next()
    elem.AddAttribute("attr1", "value1")
    attribute, ok := elem.Attribute("test")
    if !ok {
            continue
        }
		
    attribute.Set(strings.ToUpper(attribute.Value()))
}

result := dom.Render()
fmt.Println(result)

// Output:
// <?xml version="1.0" encoding="UTF-8"?>
// <foo test="TRUE" attr1="value1">
//     <id>10</id>
//     <name>foo name</name>
//     <address><new-elem>New element value</new-elem></address>
//     <quantity>123</quantity>
//     <price>50.5</price>
//     <type>fType</type>
// </foo>

Options

Supported options:

  • ElementsChangesSize - in case of lazy rendering all the changes are buffered. In order to ignore lookup time with the Map, it is possible to update changes directly in the slice. Default is 30
  • AttributesChangesSize - same as above, but for the attributes. Default is 30

Filters

You can create filters by parsing xpath, value of attribute is optional:

filters := option.NewFilters()
newFilters, err := xml.NewFilters("foo/price[currency]", "address[country and city]/street")
// handle error
filters.Add(newFilters...)

Or

filters, err := xml.FiltersOf("foo/price[currency]", "address[country and city]/street")
// handle error

Selectors

You can create selectors by parsing xpath, value of attribute is required:

selectors, err := xml.NewSelectors("foo[test='true' and lang!='eng']/address") option.NewFilters()
// handle error

Supported:

  • Attributes selectors can be combined with and
  • Equal (=) / Not Equal (!=)