xml

package
v0.0.0-...-994bc1c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 23, 2023 License: Apache-2.0 Imports: 7 Imported by: 0

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 (!=)

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func FiltersOf

func FiltersOf(xpaths ...string) (*option.Filters, error)

func NewFilters

func NewFilters(xpaths ...string) ([]*option.Filter, error)

NewFilters creates slice option.Filter based on given xpaths

Types

type Attribute

type Attribute struct {
	// contains filtered or unexported fields
}

Attribute represents XML element attribute

func (*Attribute) Set

func (a *Attribute) Set(value string)

Set updates attribute value

func (*Attribute) Value

func (a *Attribute) Value() string

Value returns attribute value

type AttributeSelector

type AttributeSelector struct {
	Name    string
	Value   string
	Compare ComparisonToken
}

AttributeSelector matches Element by Attribute name and value

type AttributesChangesSize

type AttributesChangesSize int

type Buffer

type Buffer struct {
	// contains filtered or unexported fields
}

Buffer hold the current XML value

func NewBuffer

func NewBuffer(size int) *Buffer

NewBuffer creates new buffer of given size.

func (*Buffer) String

func (b *Buffer) String() string

String returns String representation of the buffer

type ComparisonToken

type ComparisonToken string
const (
	EQ  ComparisonToken = "="
	NEQ ComparisonToken = "!="
)

type DOM

type DOM struct {
	// contains filtered or unexported fields
}

DOM represents DOM structure

func New

func New(template string, options ...option.Option) (*DOM, error)

New creates new VirtualDOM

Example
package main

import (
	"fmt"
	"github.com/viant/dm/option"
	"github.com/viant/dm/xml"
	"strings"
)

func main() {
	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>

func (*DOM) Document

func (d *DOM) Document() *Document

Document returns new *Document

type Document

type Document struct {
	// contains filtered or unexported fields
}

Document modifies the VirtualDOM

func (*Document) Render

func (d *Document) Render() string

Render returns XML value after changes

func (*Document) Select

func (d *Document) Select(selectors ...Selector) *Iterator

Select returns Iterator over matching Elements

func (*Document) SelectFirst

func (d *Document) SelectFirst(selectors ...Selector) (*Element, bool)

SelectFirst returns first Element that matches selectors

type Element

type Element struct {
	// contains filtered or unexported fields
}

Element represents XML Element

func (*Element) AddAttribute

func (e *Element) AddAttribute(key string, value string)

AddAttribute adds new Attribute

func (*Element) AddElement

func (e *Element) AddElement(value string)

AddElement adds new Element value

func (*Element) Attribute

func (e *Element) Attribute(attribute string) (*Attribute, bool)

Attribute returns Element attribute with given name

func (*Element) InsertAfter

func (e *Element) InsertAfter(element string)

InsertAfter inserts new element after receiver

func (*Element) InsertBefore

func (e *Element) InsertBefore(element string)

InsertBefore inserts new element before receiver

func (*Element) ReplaceWith

func (e *Element) ReplaceWith(newElement string)

func (*Element) SetAttribute

func (e *Element) SetAttribute(key, value string)

SetAttribute update attribute value, or creates new one if it doesn't exist.

func (*Element) SetValue

func (e *Element) SetValue(value string)

SetValue updates Element value

func (*Element) Value

func (e *Element) Value() string

Value returns Element value

type ElementsChangesSize

type ElementsChangesSize int

type Iterator

type Iterator struct {
	// contains filtered or unexported fields
}

Iterator iterates over matching Elements

func (*Iterator) Has

func (i *Iterator) Has() bool

Has returns true if there are more matching elements

func (*Iterator) Next

func (i *Iterator) Next() (*Element, error)

Next returns next matching Element

type Selector

type Selector struct {
	Name       string
	Attributes []AttributeSelector
	MatchAny   bool
}

Selector matches Element by name

func NewSelectors

func NewSelectors(xpath string) ([]Selector, error)

NewSelectors creates Selectors from xpath

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL