Documentation ¶
Overview ¶
Package xmlwriter provides a fast, non-cached, forward-only way to generate XML data.
The API is based heavily on libxml's xmlwriter API [1], which is itself based on C#'s XmlWriter [2].
[1] http://xmlsoft.org/html/libxml-xmlwriter.html [2] https://msdn.microsoft.com/en-us/library/system.xml.xmlwriter(v=vs.110).aspx
It offers some advantages over Go's default encoding/xml package and some tradeoffs. You can have complete control of the generated documents and it uses very little memory.
There are two styles for interacting with the writer: structured and heap-friendly. If you want a visual representation of the hierarchy of some of your writes in your code and you don't care about a few instances of memory escaping to the heap (and most of the time you won't), you can use the structured API. If you are writing a code generator or your interactions with the API are minimal, you should use the direct API.
Creating ¶
xmlwriter.Writer{} takes any io.Writer, along with a variable list of options.
b := &bytes.Buffer{} w := xmlwriter.Open(b)
xmlwriter options are based on Dave Cheney's functional options pattern (https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis):
w := xmlwriter.NewWriter(b, xmlwriter.WithIndent())
Provided options are:
- WithIndent()
- WithIndentString(string)
Overview ¶
Using the structured API, you might express a small tree of elements like this. These nodes will escape to the heap, but judicious use of this nesting can make certain structures a lot more readable by representing the desired XML hierarchy in the code that produces it:
ec := &xmlwriter.ErrCollector{} defer ec.Panic() ec.Do( w.Start(xmlwriter.Doc{}), w.Start(xmlwriter.Elem{ Name: "foo", Attrs: []xmlwriter.Attr{ {Name: "a1", Value: "val1"}, {Name: "a2", Value: "val2"}, }, Content: []xmlwriter.Writable{ xmlwriter.Comment{"hello"}, xmlwriter.Elem{ Name: "bar", Attrs: []xmlwriter.Attr{ {Name: "a1", Value: "val1"}, {Name: "a2", Value: "val2"}, }, Content: []xmlwriter.Writable{ xmlwriter.Elem{Name: "baz"}, }, }, }, }), w.EndAllFlush(), )
The code can be made even less dense by importing xmlwriter with a prefix: `import xw "github.com/shabbyrobe/xmlwriter"`
The same output is possible with the heap-friendy API. This has a lot more stutter and it's harder to tell the hierarchical relationship just by looking at the code, but there are no heap escapes this way:
ec := &xmlwriter.ErrCollector{} defer ec.Panic() ec.Do( w.StartDoc(xmlwriter.Doc{}) w.StartElem(xmlwriter.Elem{Name: "foo"}) w.WriteAttr(xmlwriter.Attr{Name: "a1", Value: "val1"}) w.WriteAttr(xmlwriter.Attr{Name: "a2", Value: "val2"}) w.WriteComment(xmlwriter.Comment{"hello"}) w.StartElem(xmlwriter.Elem{Name: "bar"}) w.WriteAttr(xmlwriter.Attr{Name: "a1", Value: "val1"}) w.WriteAttr(xmlwriter.Attr{Name: "a2", Value: "val2"}) w.StartElem(xmlwriter.Elem{Name: "baz"}) w.EndAllFlush() )
Use whichever API reads best in your code, but favour the latter style in all code generators and performance hotspots.
Flush ¶
xmlwriter.Writer extends bufio.Writer! Don't forget to flush otherwise you'll lose data.
There are two ways to flush:
- Writer.Flush()
- Writer.EndAllFlush()
The EndAllFlush form is just a convenience, it calls EndAll() and Flush() for you.
Start and Write and Block ¶
Nodes which can have children can be passed to `Writer.Start()`. This adds them to the stack and opens them, allowing children to be added.
w.Start(xmlwriter.Elem{Name: "foo"}, xmlwriter.Elem{Name: "bar"}, xmlwriter.Elem{Name: "baz"}) w.EndAllFlush()
Becomes: <foo><bar><baz/></bar></foo>
Nodes which have no children, or nodes which can be opened and fully closed with only a trivial amount of information, can be passed to `Writer.Write()`. If written nodes are put on to the stack, they will be popped before Write returns.
w.Write(xmlwriter.Elem{Name: "foo"}, xmlwriter.Elem{Name: "bar"}, xmlwriter.Elem{Name: "baz"})
Becomes: <foo/><bar/><baz/>
Block takes a Startable and a variable number of Writable nodes. The Startable will be opened, the Writables will be written, then the Startable will be closed:
w.Block(xmlwriter.Elem{Name: "foo"}, xmlwriter.Comment{"comment!"}, xmlwriter.CData{"cdata."}, xmlwriter.Elem{Name: "bar"}, )
Becomes:
<foo><!--comment!--><![CDATA[cdata.]><bar/></foo>
End ¶
There are several ways to end an element. Choose the End that's right for you!
- EndAll()
- EndAllFlush()
- EndAny()
- End(NodeKind)
- End(NodeKind, name...)
- EndToDepth(int, NodeKind)
- EndToDepth(int, NodeKind, name...)
- EndDoc()
- End...() Where ... is the name of a startable node struct, End ends that node kind. The following two are equivalent: EndElem() End(ElemNode)
Nodes ¶
Nodes as they are written can be in three states: StateOpen, StateOpened or StateEnd. StateOpen == "<elem". StateOpened == "<elem>". StateEnd == "<elem></elem>".
Node structs are available for writing in the following hierarchy. Nodes which are "Startable" (passed to `writer.Start(n)`) are marked with an S. Nodes which are "Writable" (passed to `writer.Write(n)`) are marked with a W.
- xmlwriter.Raw* (W) - xmlwriter.Doc (S)
- xmlwriter.DTD (S)
- xmlwriter.DTDEntity (W)
- xmlwriter.DTDElement (W)
- xmlwriter.DTDAttrList (S, W)
- xmlwriter.DTDAttr (W)
- xmlwriter.Notation (W)
- xmlwriter.Comment (S, W)
- xmlwriter.PI (W)
- xmlwriter.Comment (S, W)
- xmlwriter.Elem (S, W)
- xmlwriter.Attr (W)
- xmlwriter.PI (W)
- xmlwriter.Text (W)
- xmlwriter.Comment (S, W)
- xmlwriter.CommentContent (W)
- xmlwriter.CData (S, W)
- xmlwriter.CDataContent (W)
* `xmlwriter.Raw` can be written anywhere, at any time. If a node is in the "open" state but not in the "opened" state, for example you have started an element and written an attribute, writing "raw" will add the content to the inside of the element opening tag unless you call `w.Next()`.
Every node has a corresponding NodeKind constant, which can be found by affixing "Node" to the struct name, i.e. "xmlwriter.Elem" becomes "xmlwriter.ElemNode". These are used for calls to Writer.End().
xmlwriter.Attr{} values can be assigned from any golang primitive like so:
Attr{Name: "foo"}.Int(5) Attr{Name: "foo"}.Uint64(5) Attr{Name: "foo"}.Float64(1.234)
Encodings ¶
xmlwriter supports encoders from the golang.org/x/text/encoding package. UTF-8 strings written in from golang will be converted on the fly and the document declaration will be written correctly.
To write your XML using the windows-1252 encoder:
b := &bytes.Buffer{} enc := charmap.Windows1252.NewEncoder() w := xw.OpenEncoding(b, "windows-1252", enc) xw.Must(w.Start(xw.Doc{})) xw.Must(w.Start(xw.Elem{Name: "hello"})) xw.Must(w.Write(xw.Text("Résumé"))) w.EndAllFlush() os.Stdout.Write(b.Bytes())
The document line will look like this:
<?xml version="1.0" encoding="windows-1252"?>
Index ¶
- Constants
- func CheckChars(chars string, strict bool) error
- func CheckEncoding(encoding string) error
- func CheckName(name string) error
- func CheckPubID(pubid string) error
- type Attr
- func (a Attr) Bool(v bool) Attr
- func (a Attr) Float32(v float32) Attr
- func (a Attr) Float64(v float64) Attr
- func (a Attr) Int(v int) Attr
- func (a Attr) Int16(v int16) Attr
- func (a Attr) Int32(v int32) Attr
- func (a Attr) Int64(v int64) Attr
- func (a Attr) Int8(v int8) Attr
- func (a Attr) Uint(v int) Attr
- func (a Attr) Uint16(v uint16) Attr
- func (a Attr) Uint32(v uint32) Attr
- func (a Attr) Uint64(v uint64) Attr
- func (a Attr) Uint8(v uint8) Attr
- type CData
- type CDataContent
- type Comment
- type CommentContent
- type DTD
- type DTDAttList
- type DTDAttr
- type DTDAttrDefaultType
- type DTDAttrType
- type DTDElem
- type DTDEntity
- type Doc
- type Elem
- type ErrCollector
- type Event
- type Indenter
- type Node
- type NodeKind
- type NodeState
- type Notation
- type Option
- type PI
- type Raw
- type StandardIndenter
- type Startable
- type Text
- type Writable
- type Writer
- func (w *Writer) Block(start Startable, nodes ...Writable) error
- func (w *Writer) Depth() int
- func (w *Writer) End(kind NodeKind, name ...string) error
- func (w *Writer) EndAll() error
- func (w *Writer) EndAllFlush() error
- func (w *Writer) EndAny() error
- func (w *Writer) EndCData() (err error)
- func (w *Writer) EndComment() (err error)
- func (w *Writer) EndDTD() (err error)
- func (w *Writer) EndDTDAttList() (err error)
- func (w *Writer) EndDoc() (err error)
- func (w *Writer) EndElem(name ...string) error
- func (w *Writer) EndElemFull(name ...string) error
- func (w *Writer) EndToDepth(depth int, kind NodeKind, name ...string) error
- func (w *Writer) Flush() error
- func (w *Writer) Next() error
- func (w *Writer) Start(nodes ...Startable) error
- func (w *Writer) StartCData(cdata CData) error
- func (w *Writer) StartComment(comment Comment) error
- func (w *Writer) StartDTD(dtd DTD) error
- func (w *Writer) StartDTDAttList(al DTDAttList) error
- func (w *Writer) StartDoc(doc Doc) error
- func (w *Writer) StartElem(elem Elem) error
- func (w *Writer) Write(nodes ...Writable) error
- func (w *Writer) WriteAttr(attrs ...Attr) (err error)
- func (w *Writer) WriteCData(cdata CData) (err error)
- func (w *Writer) WriteCDataContent(cdata string) error
- func (w *Writer) WriteComment(comment Comment) (err error)
- func (w *Writer) WriteCommentContent(comment string) error
- func (w *Writer) WriteDTDAttList(attlist DTDAttList) (err error)
- func (w *Writer) WriteDTDAttr(attr DTDAttr) (err error)
- func (w *Writer) WriteDTDElem(el DTDElem) error
- func (w *Writer) WriteDTDEntity(entity DTDEntity) error
- func (w *Writer) WriteElem(elem Elem) (err error)
- func (w *Writer) WriteNotation(n Notation) (err error)
- func (w *Writer) WritePI(pi PI) error
- func (w *Writer) WriteRaw(raw string) error
- func (w *Writer) WriteText(text string) (err error)
Constants ¶
const ( // DTDElemEmpty is a DTDElem Decl used when the element is empty. DTDElemEmpty = "EMPTY" // DTDElemAny is a DTDElem Decl used when the element can contain any element. DTDElemAny = "ANY" // DTDElemPCData is a DTDElem Decl used when the element can contain parsed // character data. DTDElemPCData = "#PCDATA" )
Variables ¶
This section is empty.
Functions ¶
func CheckChars ¶
CheckChars ensures a string contains characters which are valid in a Text{} node: https://www.w3.org/TR/xml/#NT-Char The 'strict' argument (which xmlwriter should activate by default) ensures that unicode characters referenced in the note are also excluded.
func CheckEncoding ¶
CheckEncoding validates the characters in a Doc{} node's encoding="..." attribute based on the following production rule:
[A-Za-z] ([A-Za-z0-9._] | '-')*
func CheckName ¶
CheckName ensures a string satisfies the following production rules: https://www.w3.org/TR/xml/#NT-NameStartChar, with the exception that it does not return an error on an empty string.
func CheckPubID ¶
CheckPubID validates a string according to the following production rule: https://www.w3.org/TR/xml/#NT-PubidLiteral
Types ¶
type Attr ¶
Attr represents an XML attribute to be written by the Writer.
type CData ¶
type CData struct {
Content string
}
CData represents an XML CData section which can be written or started by the Writer.
type CDataContent ¶
type CDataContent string
CDataContent represents a text portion of an XML CData section which can be written after a CData is Started.
type Comment ¶
type Comment struct {
Content string
}
Comment represents an XML comment section which can be written or started by the Writer.
type CommentContent ¶
type CommentContent string
CommentContent represents a text portion of an XML comment which can be written after a Comment is Started.
type DTDAttList ¶
DTDAttList represents a DTD attribute list to be written by the Writer.
Examples:
DTDAttList{Name: "yep", Attrs: []DTDAttr{ {Name: "a1", Type: DTDAttrString, Required: true}, {Name: "a2", Type: DTDAttrString, Required: true}, }})) <!ATTLIST yep a1 CDATA #REQUIRED a2 CDATA #REQUIRED>
type DTDAttr ¶
type DTDAttr struct { Name string Type DTDAttrType Default DTDAttrDefaultType Value string }
DTDAttr represents a DTD attribute to be written by the Writer.
type DTDAttrDefaultType ¶
type DTDAttrDefaultType int
DTDAttrDefaultType represents the possible values from the DefaultDecl production in the DTD spec: https://www.w3.org/TR/REC-xml/#NT-DefaultDecl
const ( // If Value is empty, this attribute is DTDAttrImplied, otherwise it will be a // standard DTDAttrDefault value (without #FIXED). If you need to represent the // empty string as your default value, you will need to explicitly use DTDAttrDefault // or DTDAttrFixed. DTDAttrInfer DTDAttrDefaultType = iota // DTDAttr.Value represents the default for this attribute. Value may be an // empty string. DTDAttrDefault // The attribute MUST always be provided. DTDAttr.Value must be empty. DTDAttrRequired // No default value is provided. DTDAttr.Value must be empty. DTDAttrImplied // The #FIXED keyword states that the attribute MUST always have the default value. // If the declaration is neither #REQUIRED nor #IMPLIED, then the AttValue value // contains the declared default value. DTDAttrFixed )
type DTDAttrType ¶
type DTDAttrType string
DTDAttrType constrains the valid values for the Type property of the DTDAttr struct.
const ( DTDAttrString DTDAttrType = "CDATA" DTDAttrID DTDAttrType = "ID" DTDAttrIDRef DTDAttrType = "IDREF" DTDAttrIDRefs DTDAttrType = "IDREFS" DTDAttrEntity DTDAttrType = "ENTITY" DTDAttrEntities DTDAttrType = "ENTITIES" DTDAttrNmtoken DTDAttrType = "NMTOKEN" DTDAttrNmtokens DTDAttrType = "NMTOKENS" )
type DTDElem ¶
DTDElem represents a DTD element definition to be written by the Writer.
Examples:
DTDElem{Name: "elem", Decl: DTDElemEmpty} -> <!ELEMENT elem EMPTY> DTDElem{Name: "elem", Decl: "(a|b)*"} -> <!ELEMENT elem (a|b)*>
type DTDEntity ¶
type DTDEntity struct { Name string Content string IsPE bool PublicID string SystemID string NDataID string }
DTDEntity represents a DTD entity definition to be written by the Writer.
Examples:
DTDEntity{Name: "pants", Content: ">"} <!ENTITY pants ">"> DTDEntity{Name: "pants", SystemID: "sys"} <!ENTITY pants SYSTEM "sys"> DTDEntity{Name: "pants", SystemID: "sys", IsPE: true} <!ENTITY % pants SYSTEM "sys"> DTDEntity{Name: "pants", SystemID: "sys", PublicID: "pub", NDataID: "nd"} <!ENTITY pants PUBLIC "pub" "sys" NDATA nd>
type Doc ¶
type Doc struct { // Do not print 'encoding="..."' into the document opening SuppressEncoding bool // Override Writer.Encoding with this string if not nil ForcedEncoding *string // Do not print 'version="..."' into the document opening SuppressVersion bool // Override Writer.Version with this string if not nil ForcedVersion *string // If nil, do not print 'standalone="..."' Standalone *bool }
Doc represents an XML document which can be started by the writer.
Examples (assuming UTF-8 encoding used with Writer):
Doc{} <?xml version="1.0" encoding="UTF-8"?> Doc{}.WithStandalone(false) <?xml version="1.0" encoding="UTF-8" standalone="no"?> Doc{}.WithStandalone(true) <?xml version="1.0" encoding="UTF-8" standalone="yes"?> Doc{SuppressVersion: true, SuppressEncoding: true} <?xml ?> Doc{}.ForceVersion("pants").ForceEncoding("pants") <?xml version="pants" encoding="pants" ?>
func (Doc) ForceEncoding ¶
ForceEncoding is a fluent convenience function for assigning a non-pointer string to Doc.ForcedEncoding.
func (Doc) ForceVersion ¶
ForceVersion is a fluent convenience function for assigning a non-pointer string to Doc.ForcedVersion.
func (Doc) WithStandalone ¶
WithStandalone is a fluent convenience function for assigning a non-pointer bool to Doc.Standalone
type Elem ¶
type Elem struct { Prefix string URI string Name string Attrs []Attr // A tree of writable nodes can be assigned to this - they will // be written when the node is opened. Not heap-friendly. Content []Writable // When ending this element, use the full style, i.e. <foo></foo> // even if the element is empty. Full bool // contains filtered or unexported fields }
Elem represents an XML element to be written by the writer.
type ErrCollector ¶
ErrCollector allows you to defer raising or accumulating an error until after a series of procedural calls.
ErrCollector it is intended to help cut down on boilerplate like this:
if err := w.Start(xmlwriter.Doc{}); err != nil { return err } if err := w.Start(xmlwriter.Elem{Name: "elem"}); err != nil { return err } if err := w.Start(xmlwriter.Attr{Name: "attr", Value: "yep"}); err != nil { return err } if err := w.Start(xmlwriter.Attr{Name: "attr2", Value: "nup"}); err != nil { return err }
For any sufficiently complex procedural XML assembly, this is patently ridiculous. ErrCollector allows you to assume that it's ok to keep writing until the end of a controlled block, then fail with the first error that occurred. In complex procedures, ErrCollector is far more succinct and mirrors an idiom used internally in the library, which was itself cribbed from the stdlib's xml package (see cachedWriteError).
For functions that return an error:
func pants(w *xmlwriter.Writer) (err error) { ec := &xmlwriter.ErrCollector{} defer ec.Set(&err) ec.Do( w.Start(xmlwriter.Doc{}), w.Start(xmlwriter.Elem{Name: "elem"}), w.Start(xmlwriter.Attr{Name: "elem", Value: "yep"}), w.Start(xmlwriter.Attr{Name: "elem", Value: "nup"}), ) return }
If you want to panic instead, just substitute `defer ec.Set(&err)` with `defer ec.Panic()`
It is entirely the responsibility of the library's user to remember to call either `ec.Set()` or `ec.Panic()`. If you don't, you'll be swallowing errors.
func (*ErrCollector) Do ¶
func (e *ErrCollector) Do(errs ...error)
Do collects the first error in a list of errors and holds on to it.
If you pass the result of multiple functions to Do, they will not be short circuited on failure - the first error is retained by the collector and the rest are discarded. It is only intended to be used when you know that subsequent calls after the first error are safe to make.
func (*ErrCollector) Error ¶
func (e *ErrCollector) Error() string
Error implements the error interface.
func (*ErrCollector) Must ¶
func (e *ErrCollector) Must(errs ...error)
Must collects the first error in a list of errors and panics with it.
func (*ErrCollector) Panic ¶
func (e *ErrCollector) Panic()
Panic causes the collector to panic if any error has been collected.
This should be called in a defer:
func pants() { ec := &xmlwriter.ErrCollector{} defer ec.Panic() ec.Do(fmt.Errorf("this will panic at the end")) fmt.Printf("This will print") }
func (*ErrCollector) Set ¶
func (e *ErrCollector) Set(err *error)
Set assigns the collector's internal error to an external error variable.
This should be called in a defer with a named return to allow an error to be easily returned if one is collected:
func pants() (err error) { ec := &xmlwriter.ErrCollector{} defer ec.Set(&err) ec.Do(fmt.Errorf("this error will be returned by the pants function")) fmt.Printf("This will print") }
func (*ErrCollector) Unwrap ¶
func (e *ErrCollector) Unwrap() error
Unwrap satisfies the requirement of `errors.Unwrap()`, to allow testing ErrCollector with e.g. `errors.Is()` and `errors.As()`.
type Event ¶
Event is raised when a node changes state in the writer. It is currently only relevant to the Indenter but may become an event system in a later version.
type Indenter ¶
type Indenter interface { // Indent is called every time a node transitions from one State // to another. This allows whitespace (or anything, really) to be // injected in between any two pieces that the writer writes to the // document. Indent(w *Writer, last Event, next Event) error // Wrap is called on every Text and CommentContent node - if you // want your indenter to place text slabs into nicely formatted // blocks, the logic goes here. Wrap(content string) string }
Indenter allows custom indenting strategies to be written for pretty printing the resultant XML.
Writing one of these little nightmares is not for the faint of heart - it's a monumental pain to get indenting rules right. See StandardIndenter for a glimpse into the abyss.
type Node ¶
type Node interface {
// contains filtered or unexported methods
}
Node represents an item which the Writer can Start and/or Write. It is the wider type for Startable and Writable.
type NodeKind ¶
type NodeKind int
NodeKind is the kind of the node. Yep.
const ( NoNode NodeKind = iota AttrNode CDataNode CDataContentNode CommentNode CommentContentNode DTDNode DTDAttListNode DTDAttrNode DTDElemNode DTDEntityNode DocNode ElemNode NotationNode PINode RawNode TextNode )
Range of allowed NodeKind values.
type Notation ¶
Notation represents an XML notation declaration to be written by the Writer. https://www.w3.org/TR/xml/#dt-notation
type Option ¶
type Option func(w *Writer)
Option is an option to the Writer.
func WithIndent ¶
func WithIndent() Option
WithIndent sets the Writer up to indent XML elements to make them easier to read using the StandardIndenter:
w := xmlwriter.Open(b, xmlwriter.WithIndent())
func WithIndentString ¶
WithIndentString configures the Writer with a StandardIndenter using a specific indent string:
w := xmlwriter.Open(b, xmlwriter.WithIndentString(" "))
type Raw ¶
type Raw string
Raw represents a raw string to be written by the Writer. See Writer.WriteRaw()
type StandardIndenter ¶
type StandardIndenter struct { // Output whitespace control IndentString string // contains filtered or unexported fields }
StandardIndenter implements a primitive Indenter strategy for pretty printing the Writer's XML output.
StandardIndenter is used by the WithIndent writer option:
w := xmlwriter.Open(b, xmlwriter.WithIndent())
func NewStandardIndenter ¶
func NewStandardIndenter() *StandardIndenter
NewStandardIndenter creates a StandardIndenter.
func (*StandardIndenter) Indent ¶
func (s *StandardIndenter) Indent(w *Writer, last Event, next Event) error
Indent satisfies the Indenter interface.
func (*StandardIndenter) Wrap ¶
func (s *StandardIndenter) Wrap(content string) string
Wrap satisfies the Indenter interface.
type Startable ¶
type Startable interface { Node // contains filtered or unexported methods }
Startable is a node which can be passed to xmlwriter.Start() - any node which can have children is Startable.
type Text ¶
type Text string
Text represents an XML text section to be written by the Writer. See Writer.WriteText()
type Writable ¶
type Writable interface { Node // contains filtered or unexported methods }
Writable is a node which can be passed to xmlwriter.Write(). Writables may or may not have children. Writable nodes can not be passed to xmlwriter.Start().
type Writer ¶
type Writer struct { // Perform validation on output. Defaults to true when created using Open(). Enforce bool // When enforcing and checking characters, excludes an additional set of // compatibility chars. Defaults to true. See check.go/CheckChars. StrictChars bool // Version is placed into the `version="..."` attribute when writing a Doc{}. // Defaults to 1.0. Version string // Determines how much memory the internal buffer will use. Set to 0 to use // the default. InitialBufSize int // Defaults to \n. NewlineString string // Controls the indenting process used by the writer. Indenter Indenter // contains filtered or unexported fields }
Writer writes XML to an io.Writer.
func OpenEncoding ¶
OpenEncoding opens the Writer using the supplied encoding.
This example opens an XML writer using the utf16-be encoding:
enc := unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM).NewEncoder() w := xmlwriter.OpenEncoding(b, "utf-16be", enc)
You should still write UTF-8 strings to the writer - they are converted on the fly to the target encoding.
func (*Writer) Block ¶
Block is a convenience function that takes a parent node and a list of direct children. The parent node is passed to Writer.Start(), the children are passed to Write(), then the parent passed to End().
func (*Writer) End ¶
End ends the current node if it is of the kind specified, and also optionally (and if relevant) if the name matches. If one string is passed to name, it is compared to the node's Name field. If two strings are passed to name, the first is compared to the node's Prefix field, the second is compared to the node's Name field. This form works with the following node types: ElemNode, DTDNode, DTDAttListNode.
func (*Writer) EndAllFlush ¶
EndAllFlush ends every node on the stack and calls Flush()
func (*Writer) EndCData ¶
EndCData pops a CData node from the writer's stack, or returns an error if the current node is not a CData.
func (*Writer) EndComment ¶
EndComment pops a Comment node from the writer's stack, or returns an error if the current node is not a Comment.
func (*Writer) EndDTD ¶
EndDTD pops a DTD node from the writer's stack, or returns an error if the current node is not a DTD.
func (*Writer) EndDTDAttList ¶
EndDTDAttList pops a DTDAttList node from the writer's stack, or returns an error if the current node is not a DTDAttList.
func (*Writer) EndDoc ¶
EndDoc ends the current xmlwriter.Doc{} and any node in between. This is not the same as calling End(DocNode), which will only end a Doc{} if it is the current node on the stack.
func (*Writer) EndElem ¶
EndElem pops an Elem node from the writer's stack, or returns an error if the current node is not an Elem. If the Elem has had no children written, it will be closed using the short close style: "<tag/>"
func (*Writer) EndElemFull ¶
EndElemFull pops an Elem node from the writer's stack, or returns an error if the current node is not an Elem. It will always be closed using the full element close style even if it contains no children: "<tag></tag>".
func (*Writer) EndToDepth ¶
EndToDepth ends all nodes in the stack up to the supplied depth. The last node must match NodeKind and, if provided and applicable for the node type, the name. This is useful if you want to ensure that everything you open inside a particular scope is closed at the end:
func outer() { w.Start(Elem{Name: "pants"}) inner() // result: // <pants><foo><bar/></foo> } func inner() { d := w.Depth() defer w.EndToDepth(d, NodeElem) w.Start(Elem{Name: "foo"}) w.Start(Elem{Name: "bar"}) }
func (*Writer) Flush ¶
Flush ensures the output buffer accumuated inside the Writer is fully written to the underlying io.Writer.
func (*Writer) Next ¶
Next ensures that the current element is opened and the next one can be started. It is called for all node types except Raw{}. This is so that you can write raw strings inside elements that are open but not opened. See StateOpen and StateOpened for more details on this distinction.
func (*Writer) StartCData ¶
StartCData pushes an XML CData node onto the writer's stack. WriteCDataContent can be used to write contents.
func (*Writer) StartComment ¶
StartComment pushes an XML comment node onto the writer's stack. WriteCommentContent can be used to write contents.
func (*Writer) StartDTDAttList ¶
func (w *Writer) StartDTDAttList(al DTDAttList) error
StartDTDAttList pushes a Document Type Declaration node onto the writer's stack.
func (*Writer) WriteCData ¶
WriteCData writes a complete XML CData section. It can be written inside an Elem or as a top-level node.
func (*Writer) WriteCDataContent ¶
WriteCDataContent writes text inside an already-started XML CData node.
func (*Writer) WriteComment ¶
WriteComment writes a complete XML Comment section. It can be written inside an Elem, a DTD, a Doc, or as a top-level node.
func (*Writer) WriteCommentContent ¶
WriteCommentContent writes text inside an already-started XML Comment node.
func (*Writer) WriteDTDAttList ¶
func (w *Writer) WriteDTDAttList(attlist DTDAttList) (err error)
WriteDTDAttList writes a DTD Attribute List to the output. It can be written inside a DTD or as a top-level node.
func (*Writer) WriteDTDAttr ¶
WriteDTDAttr writes a DTD Attribute definition to the output. It can be written inside a DTDAttList or as a top-level node.
func (*Writer) WriteDTDElem ¶
WriteDTDElem writes a DTD Element definition to the output. It can be written inside a DTD or as a top-level node.
func (*Writer) WriteDTDEntity ¶
WriteDTDEntity writes a DTD Entity definition to the output. It can be written inside a DTD or as a top-level node.
func (*Writer) WriteElem ¶
WriteElem writes a complete XML Element. It can be written inside an Elem, a Doc, or as a top-level node.
Nested elements and attributes can be written by assigning to the members of the Elem struct to an arbitrary depth (though be warned that this can cause heap escapes):
e := Elem{ Name: "outer", Attrs: []Attr{Attr{Name: "key", Value: "val"}}, Content: []Writable{Elem{Name: "inner"}}, }
func (*Writer) WriteNotation ¶
WriteNotation writes an XML notation to the output. It can be written inside a DTD or as a top-level node.
func (*Writer) WritePI ¶
WritePI writes an XML processing instruction to the output. It can be written inside a Doc, an Elem or as a top-level node.