fxml

package module
v1.2.4 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2022 License: MIT Imports: 10 Imported by: 0

README

fxml - FreeStyle XML Parser

godoc

This package provides a simple parser which reads a XML document and output a tree structure, which does not need a pre-defined struct, hence the name "FreeStyle".

See godoc for more information.

Documentation

Overview

fxml - FreeStyle XML Parser

This package provides a simple parser which reads a XML document and output a tree structure, which does not need a pre-defined “struct”, hence the name “FreeStyle”.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Converter

type Converter interface {
	Init(string) error
	ToString([]byte) string
}

Charset conversion interface. This package only outputs UTF-8 text, all other charsets are either not accepted or silently converted to UTF-8. The behavior is defined by the actual converter.

By default, the “null” converter is used, which does not accept non UTF-8 text, i.e. the “ProcInst” of XML document must be:

<?xml version="1.0" encoding="UTF-8"?>

To allow other charsets, use the “iconv” converter:

go build -tags iconv

Beware that the “iconv” converter uses “libiconv” through CGo. See: https://github.com/djimenez/iconv-go

type NConv

type NConv struct{}

"null" converter, which output UTF-8 text as-is, and do not accept non UTF-8 characters. This converter does not require “libiconv”.

Note: the Converter interface (i.e. this struct) is used internally by the parser, do NOT use it in your code.

func (*NConv) Init

func (ic *NConv) Init(charset string) error

Initialize the converter. This function is called by the parser internally.

func (NConv) ToString

func (ic NConv) ToString(v []byte) string

Convert a byte slice to string. This function is called by the parser internally.

type XMLTree

type XMLTree struct {
	Name      xml.Name
	Attr      []xml.Attr `json:",omitempty"`
	Comment   string     `json:",omitempty"`
	Directive string     `json:",omitempty"`
	Text      string     `json:",omitempty"`
	Children  []XMLTree  `json:",omitempty"`
}

func Parse

func Parse(r io.Reader) (*XMLTree, error)

Construct a XMLTree from the given io.Reader

Example

parse XML data from a reader

package main

import (
	"bytes"
	"encoding/json"
	"os"

	"github.com/xrfang/fxml"
)

func main() {
	b := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
	<kml xmlns="http://www.opengis.net/kml/2.2"
	  xmlns:gx="http://www.google.com/kml/ext/2.2"
	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	  <Document id="example">
		<name>Map of the region</name>
	  </Document>
	</kml>`)
	xt, err := fxml.Parse(b)
	if err != nil {
		panic(err)
	}
	je := json.NewEncoder(os.Stdout)
	je.SetIndent("", "    ")
	je.Encode(xt)
}
Output:

{
   "Name": {
       "Space": "",
       "Local": "kml"
   },
   "Attr": [
       {
           "Name": {
               "Space": "",
               "Local": "xmlns"
           },
           "Value": "http://www.opengis.net/kml/2.2"
       },
       {
           "Name": {
               "Space": "xmlns",
               "Local": "gx"
           },
           "Value": "http://www.google.com/kml/ext/2.2"
       },
       {
           "Name": {
               "Space": "xmlns",
               "Local": "xsi"
           },
           "Value": "http://www.w3.org/2001/XMLSchema-instance"
       }
   ],
   "Text": "\n\t",
   "Children": [
       {
           "Name": {
               "Space": "",
               "Local": "Document"
           },
           "Attr": [
               {
                   "Name": {
                       "Space": "",
                       "Local": "id"
                   },
                   "Value": "example"
               }
           ],
           "Text": "\n\t  ",
           "Children": [
               {
                   "Name": {
                       "Space": "",
                       "Local": "name"
                   },
                   "Text": "Map of the region"
               }
           ]
       }
   ]
}

func (XMLTree) Encode

func (xt XMLTree) Encode(w io.Writer, full bool) (err error)

Output XML string to “w”. If “full” is true, prepend the standard ProcInst:

<?xml version="1.0" encoding="UTF-8"?>
Example

render XMLTree as XML string

package main

import (
	"bytes"
	"os"

	"github.com/xrfang/fxml"
)

func main() {
	b := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
	<kml xmlns="http://www.opengis.net/kml/2.2"
	  xmlns:gx="http://www.google.com/kml/ext/2.2"
	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	  <Document id="example">
		<name>Map of the region</name>
	  </Document>
	</kml>`)
	xt, err := fxml.Parse(b)
	if err != nil {
		panic(err)
	}
	xt.Encode(os.Stdout, true)
}
Output:

<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Document id="example"><name>Map of the region</name></Document></kml>

func (XMLTree) ToString added in v1.2.4

func (xt XMLTree) ToString(full bool) (string, error)

Wrapper of the Encode method.

Example

render XMLTree as XML string

package main

import (
	"bytes"
	"fmt"

	"github.com/xrfang/fxml"
)

func main() {
	b := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
	<kml xmlns="http://www.opengis.net/kml/2.2"
	  xmlns:gx="http://www.google.com/kml/ext/2.2"
	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	  <Document id="example">
		<name>Map of the region</name>
	  </Document>
	</kml>`)
	xt, err := fxml.Parse(b)
	if err != nil {
		panic(err)
	}
	str, err := xt.ToString(true)
	if err != nil {
		panic(err)
	}
	fmt.Println(str)
}
Output:

<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Document id="example"><name>Map of the region</name></Document></kml>

func (XMLTree) Traverse

func (xt XMLTree) Traverse(v XTraverser) bool

walk through the XMLTree using the given traverser.

Example

traverse a XMLTree

package main

import (
	"bytes"
	"fmt"

	"github.com/xrfang/fxml"
)

func main() {
	b := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
	<kml xmlns="http://www.opengis.net/kml/2.2"
	  xmlns:gx="http://www.google.com/kml/ext/2.2"
	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	  <Document id="example">
		<name>Map of the region</name>
	  </Document>
	</kml>`)
	xt, err := fxml.Parse(b)
	if err != nil {
		panic(err)
	}
	xt.Traverse(func(p string, xt fxml.XMLTree) bool {
		fmt.Println(p)
		return true
	})
}
Output:

kml
kml/Document
kml/Document/name

func (*XMLTree) Walk added in v1.2.0

func (xt *XMLTree) Walk(w XWalker)

walk through the XMLTree using the given walker.

Example

walk part of a XMLTree and modify node text

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"strings"

	"github.com/xrfang/fxml"
)

func main() {
	bs := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
	<style>This is root
	  <LineStyle>
        <color>red</color>
        <width>1</width>
	  </LineStyle>
	  <PolyStyle>
		<color>green</color>
		<width>2</width>
	  </PolyStyle>
	</style>`)
	xt, _ := fxml.Parse(bs)
	xt.Walk(func(ni fxml.XNodInfo, x *fxml.XMLTree) fxml.XWalkResult {
		fmt.Printf("%s|%+v\n", strings.Join(ni.Path, "/"), ni)
		x.Text = strings.ToUpper(x.Text)
		if ni.Path[len(ni.Path)-1] == "color" {
			return fxml.WRSkip
		}
		if ni.Path[len(ni.Path)-1] == "PolyStyle" {
			return fxml.WRTerm
		}
		return fxml.WRCont
	})
	je := json.NewEncoder(os.Stdout)
	je.Encode(xt)
}
Output:

style|{Path:[style] Index:0 RIndex:0}
style/|{Path:[style ] Index:0 RIndex:-3}
style/LineStyle|{Path:[style LineStyle] Index:1 RIndex:-2}
style/LineStyle/color|{Path:[style LineStyle color] Index:0 RIndex:-2}
style/PolyStyle|{Path:[style PolyStyle] Index:2 RIndex:-1}
{"Name":{"Space":"","Local":"style"},"Children":[{"Name":{"Space":"","Local":""},"Text":"THIS IS ROOT"},{"Name":{"Space":"","Local":"LineStyle"},"Children":[{"Name":{"Space":"","Local":"color"},"Text":"RED"},{"Name":{"Space":"","Local":"width"},"Text":"1"}]},{"Name":{"Space":"","Local":"PolyStyle"},"Children":[{"Name":{"Space":"","Local":"color"},"Text":"green"},{"Name":{"Space":"","Local":"width"},"Text":"2"}]}]}

type XNodInfo added in v1.2.0

type XNodInfo struct {
	//slice of element names, where the first is the root node and the
	//last is the current node
	Path []string
	//zero based index of the current node in its parent's children list
	Index int
	//reverse index of the current node in its parent's children list,
	//where -1 means the last child, -2 is the one before last and so on.
	RIndex int
}

info about the current node passing to the XWalker callback function

type XTraverser

type XTraverser func(string, XMLTree) bool

Walk the entire XML tree in depth-first order. The first parameter is a UNIX style path of the node being visited, the second parameter is the node itself. If it returns false, traverse will terminate.

type XWalkResult added in v1.2.0

type XWalkResult byte

action for the next iteration: continue (WRCont), skip remaining nodes in the same level (WRSkip) or terminate (WRTerm).

const (
	WRCont XWalkResult = iota //continue normally
	WRSkip                    //skip remaining nodes in the same level
	WRTerm                    //terminate the walk process
)

type XWalker added in v1.2.0

type XWalker func(XNodInfo, *XMLTree) XWalkResult

Walk the entire XML tree in depth-first order. The first parameter is a XNodInfo struct, the second parameter is the node itself. It returns XWalkResult indicating whether and how to proceed.

Apart from more informative XNodeInfo and better flow control, the most important difference between XWalker and XTraverser is that XWalker works on pointer of XMLTree, i.e. it allows in place modification of the tree nodes.

Jump to

Keyboard shortcuts

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