Documentation ¶
Overview ¶
Package xmlstream provides an API for streaming, transforming, and otherwise manipulating XML data.
BE ADVISED: The API is unstable and subject to change.
Index ¶
- func Encode(e TokenWriter, t TokenReader) (err error)
- func InnerReader(r io.Reader) io.Reader
- type FmtOption
- type TokenReader
- type TokenWriter
- type Transformer
- func Inspect(f func(t xml.Token)) Transformer
- func Map(mapping func(t xml.Token) xml.Token) Transformer
- func Remove(f func(t xml.Token) bool) Transformer
- func RemoveAttr(f func(start xml.StartElement, attr xml.Attr) bool) Transformer
- func RemoveElement(f func(start xml.StartElement) bool) Transformer
- Bugs
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Encode ¶
func Encode(e TokenWriter, t TokenReader) (err error)
Encode consumes a tokenizer and encodes any tokens that it outputs. If an error is returned on the Decode or Encode side, it is returned immediately. Since Encode is defined as consuming the stream until the end, io.EOF is not returned. If no error would be returned, Encode flushes the underlying encoder when it is done.
Example ¶
package main import ( "encoding/xml" "os" "strings" "mellium.im/xmlstream" ) func main() { removequote := xmlstream.Remove(func(t xml.Token) bool { switch tok := t.(type) { case xml.StartElement: return tok.Name.Local == "quote" case xml.EndElement: return tok.Name.Local == "quote" } return false }) e := xml.NewEncoder(os.Stdout) xmlstream.Encode(e, removequote(xml.NewDecoder(strings.NewReader(` <quote> <p>Foolery, sir, does walk about the orb, like the sun; it shines everywhere.</p> </quote>`)))) }
Output: <p>Foolery, sir, does walk about the orb, like the sun; it shines everywhere.</p>
func InnerReader ¶
InnerReader is an io.Reader which attempts to decode an xml.StartElement from the stream on the first call to Read (returning an error if an invalid start token is found) and returns a new reader which only reads the inner XML without parsing it or checking its validity. After the inner XML is read, the end token is parsed and if it does not exist or does not match the original start token an error is returned.
Example ¶
package main import ( "io" "os" "strings" "mellium.im/xmlstream" ) func main() { r := xmlstream.InnerReader(strings.NewReader(`<stream:features> <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'> <required/> </starttls> </stream:features>`)) io.Copy(os.Stdout, r) }
Output: <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'> <required/> </starttls>
Types ¶
type FmtOption ¶
type FmtOption func(*fmter)
FmtOption is used to configure a formatters behavior.
type TokenReader ¶
A TokenReader is anything that can decode a stream of XML tokens, including an xml.Decoder.
func Fmt ¶
func Fmt(t TokenReader, opts ...FmtOption) TokenReader
Fmt returns a transformer that indents the given XML stream. The default indentation style is to remove non-significant whitespace, start elements on a new line and indent two spaces per level.
Example (Indentation) ¶
package main import ( "bytes" "encoding/xml" "fmt" "strings" "mellium.im/xmlstream" ) func main() { tokenizer := xmlstream.Fmt(xml.NewDecoder(strings.NewReader(` <quote> <p> <!-- Chardata is not indented --> How now, my hearts! did you never see the picture of 'we three'?</p> </quote>`)), xmlstream.Prefix("\n"), xmlstream.Indent(" ")) buf := new(bytes.Buffer) e := xml.NewEncoder(buf) for t, err := tokenizer.Token(); err == nil; t, err = tokenizer.Token() { e.EncodeToken(t) } e.Flush() fmt.Println(buf.String()) }
Output: <quote> <p> <!-- Chardata is not indented --> How now, my hearts! did you never see the picture of 'we three'? </p> </quote>
type TokenWriter ¶
TokenWriter is anything that can encode tokens to an XML stream, including an xml.Encoder.
type Transformer ¶
type Transformer func(src TokenReader) TokenReader
A Transformer returns a new TokenReader that returns transformed tokens read from src.
func Inspect ¶
func Inspect(f func(t xml.Token)) Transformer
Inspect performs an operation for each token in the stream without transforming the stream in any way.
func Map ¶
func Map(mapping func(t xml.Token) xml.Token) Transformer
Map returns a Transformer that maps the tokens in the input using the given mapping.
func Remove ¶
func Remove(f func(t xml.Token) bool) Transformer
Remove returns a Transformer that removes tokens for which f matches.
Example ¶
package main import ( "bytes" "encoding/xml" "fmt" "strings" "mellium.im/xmlstream" ) func main() { removequote := xmlstream.Remove(func(t xml.Token) bool { switch tok := t.(type) { case xml.StartElement: return tok.Name.Local == "quote" case xml.EndElement: return tok.Name.Local == "quote" } return false }) tokenizer := removequote(xml.NewDecoder(strings.NewReader(` <quote> <p>Foolery, sir, does walk about the orb, like the sun; it shines everywhere.</p> </quote>`))) buf := new(bytes.Buffer) e := xml.NewEncoder(buf) for t, err := tokenizer.Token(); err == nil; t, err = tokenizer.Token() { e.EncodeToken(t) } e.Flush() fmt.Println(buf.String()) }
Output: <p>Foolery, sir, does walk about the orb, like the sun; it shines everywhere.</p>
func RemoveAttr ¶
func RemoveAttr(f func(start xml.StartElement, attr xml.Attr) bool) Transformer
RemoveAttr returns a Transformer that removes attributes from xml.StartElement's if f matches.
func RemoveElement ¶
func RemoveElement(f func(start xml.StartElement) bool) Transformer
RemoveElement returns a Transformer that removes entire elements (and their children) if f matches the elements start token.
Example ¶
package main import ( "bytes" "encoding/xml" "fmt" "strings" "mellium.im/xmlstream" ) func main() { removeen := xmlstream.RemoveElement(func(start xml.StartElement) bool { // TODO: Probably be more specific and actually check the name. if len(start.Attr) > 0 && start.Attr[0].Value == "en" { return true } return false }) tokenizer := removeen(xml.NewDecoder(strings.NewReader(` <quote> <p xml:lang="en">Thus the whirligig of time brings in his revenges.</p> <p xml:lang="fr">et c’est ainsi que la roue du temps amène les occasions de revanche.</p> </quote> `))) buf := new(bytes.Buffer) e := xml.NewEncoder(buf) for t, err := tokenizer.Token(); err == nil; t, err = tokenizer.Token() { e.EncodeToken(t) } e.Flush() fmt.Println(buf.String()) }
Output: <quote> <p xml:lang="fr">et c’est ainsi que la roue du temps amène les occasions de revanche.</p> </quote>
Notes ¶
Bugs ¶
Multiple uses of RemoveAttr will iterate over the attr list
multiple times.