xmlstream

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2025 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package xmlstream implements a lightweight XML scanner on top of encoding/xml. It keeps the flexibility of xml.Unmarshal while allowing the parsing of huge XML files.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Scanner

type Scanner struct {
	Decoder *xml.Decoder
	// contains filtered or unexported fields
}

Scanner provides a way to read a stream of XML data. It uses an xml.Decoder internally to step through the XML elements of the stream. Expose, so clients can set properties on Decoder, e.g. Strict.

Example
data := []byte(`
		<Person>
			<FullName>Jon Arbuckle</FullName>
			<Email where="home">
				<Addr>jon@example.com</Addr>
			</Email>
			<Email where='work'>
				<Addr>jon@work.com</Addr>
			</Email>
		</Person>

		<Cat>
			<Nickname>Garfield</Nickname>
			<Breed>Red British Shorthair</Breed>
		</Cat>

		<Person>
			<FullName>Dr. Liz Wilson</FullName>
			<Email where="home">
				<Addr>liz@example.com</Addr>
			</Email>
			<Email where='work'>
				<Addr>liz@work.com</Addr>
			</Email>
		</Person>
	`)

// Define custom structs to hold data.
type Email struct {
	Where string `xml:"where,attr"`
	Addr  string
}
type Person struct {
	Name   string  `xml:"FullName"`
	Emails []Email `xml:"Email"`
}
type Cat struct {
	Name  string `xml:"Nickname"`
	Breed string
}

// Create a scanner.
scanner := NewScanner(bytes.NewReader(data), new(Person), new(Cat))

// Iterate through it.
personCounter := 0
catCounter := 0
for scanner.Scan() {
	tag := scanner.Element()
	switch el := tag.(type) {
	case *Person:
		person := *el
		personCounter++
		fmt.Printf("Human N°%d: %s, %s\n", personCounter, person.Name, person.Emails)

	case *Cat:
		cat := *el
		catCounter++
		fmt.Printf("Cat N°%d: %s, %s\n", catCounter, cat.Name, cat.Breed)
	}
}

// Check errors.
if err := scanner.Err(); err != nil {
	fmt.Printf("Error while scanning XML: %v\n", err)
}
Output:

Human N°1: Jon Arbuckle, [{home jon@example.com} {work jon@work.com}]
Cat N°1: Garfield, Red British Shorthair
Human N°2: Dr. Liz Wilson, [{home liz@example.com} {work liz@work.com}]

func NewScanner

func NewScanner(r io.Reader, tags ...interface{}) *Scanner

NewScanner returns a new Scanner to read from r. Tags must be struct objects or pointer to struct objects, as defined by encoding/xml: http://golang.org/pkg/encoding/xml/#Unmarshal

func (*Scanner) Element

func (s *Scanner) Element() interface{}

Element returns a pointer to the most recent struct object generated by a call to Scan. The type of this struct matches the type of one of the custom struct passed to NewReader.

func (*Scanner) Err

func (s *Scanner) Err() error

Err returns the first non-EOF error that was encountered by the Scanner.

func (*Scanner) Scan

func (s *Scanner) Scan() bool

Scan advances the Scanner to the next XML element matching one of the struct passed to NewReader. his element will then be available through the Element method. It returns false when the scan stops, either by reaching the end of the input or an error. After Scan returns false, the Err method will return any error that occurred during scanning, except that if it was io.EOF, Err will return nil.

Jump to

Keyboard shortcuts

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