feat(ipub,ast)!: BaseElement marshaller
This commit is contained in:
@@ -36,6 +36,7 @@ type Element interface {
|
||||
InsertBefore(self, v1, insertee Element)
|
||||
InsertAfter(self, v1, insertee Element)
|
||||
|
||||
xml.Marshaler
|
||||
xml.Unmarshaler
|
||||
}
|
||||
|
||||
@@ -182,7 +183,7 @@ func (e *BaseElement) InsertBefore(self, v1, insertee Element) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *BaseElement) UnmarshalChildren(self Element, d *xml.Decoder, start xml.StartElement) error {
|
||||
func (e *BaseElement) UnmarshalXMLElement(self Element, d *xml.Decoder, start xml.StartElement) error {
|
||||
elErr := fmt.Errorf("unable to unmarshal element kind %q", self.Kind())
|
||||
|
||||
if n := self.Name(); n != (xml.Name{}) {
|
||||
@@ -232,6 +233,38 @@ func (e *BaseElement) UnmarshalChildren(self Element, d *xml.Decoder, start xml.
|
||||
}
|
||||
}
|
||||
|
||||
func (e *BaseElement) MarshalXMLElement(self Element, enc *xml.Encoder, start xml.StartElement) error {
|
||||
elErr := fmt.Errorf("unable to marshal element kind %q", self.Kind())
|
||||
|
||||
if n := self.Name(); n != (xml.Name{}) {
|
||||
start.Name = self.Name()
|
||||
}
|
||||
|
||||
ka, err := self.Kind().MarshalXMLAttr(elementKindAttrName)
|
||||
if err != nil {
|
||||
return errors.Join(elErr, err)
|
||||
}
|
||||
|
||||
start.Attr = append(start.Attr, ka)
|
||||
|
||||
data := struct {
|
||||
Children []Element `xml:",any"`
|
||||
}{Children: []Element{}}
|
||||
|
||||
for c := self.FirstChild(); c != nil; {
|
||||
data.Children = append(data.Children, c)
|
||||
c = c.NextSibling()
|
||||
}
|
||||
|
||||
err = enc.EncodeElement(&data, start)
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
return errors.Join(elErr, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureIsolated(e Element) {
|
||||
if p := e.Parent(); p != nil {
|
||||
p.RemoveChild(p, e)
|
||||
|
||||
@@ -19,7 +19,11 @@ func (e Content) Kind() ElementKind {
|
||||
return KindContent
|
||||
}
|
||||
|
||||
func (n *Content) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
return n.UnmarshalChildren(n, d, start)
|
||||
func (e *Content) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
|
||||
return e.MarshalXMLElement(e, enc, start)
|
||||
}
|
||||
|
||||
func (e *Content) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error {
|
||||
return e.UnmarshalXMLElement(e, dec, start)
|
||||
}
|
||||
|
||||
|
||||
36
ipub/ast/errors.go
Normal file
36
ipub/ast/errors.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ErrInvalidAttrName struct {
|
||||
Actual xml.Name
|
||||
Expected xml.Name
|
||||
}
|
||||
|
||||
var _ error = ErrInvalidAttrName{}
|
||||
|
||||
func (err ErrInvalidAttrName) Error() string {
|
||||
return fmt.Sprintf("attribute %q has invalid name, expected %q", fmtXMLName(err.Expected), fmtXMLName(err.Actual))
|
||||
}
|
||||
|
||||
type ErrInvalidAttrValue struct {
|
||||
Attr xml.Attr
|
||||
Message string
|
||||
}
|
||||
|
||||
var _ error = ErrInvalidAttrValue{}
|
||||
|
||||
func (err ErrInvalidAttrValue) Error() string {
|
||||
return fmt.Sprintf("attribute %q's value %q is invalid: %s", fmtXMLName(err.Attr.Name), err.Attr.Value, err.Message)
|
||||
}
|
||||
|
||||
func fmtXMLName(n xml.Name) string {
|
||||
s := n.Local
|
||||
if n.Space != "" {
|
||||
s = fmt.Sprintf("%s:%s", n.Space, n.Local)
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import (
|
||||
)
|
||||
|
||||
type Section struct {
|
||||
Body Body `xml:"body"`
|
||||
XMLName xml.Name `xml:"html"`
|
||||
Body *Body `xml:"body"`
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
@@ -22,6 +23,10 @@ func (e Body) Kind() ElementKind {
|
||||
return KindBody
|
||||
}
|
||||
|
||||
func (n *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
return n.UnmarshalChildren(n, d, start)
|
||||
func (e *Body) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
|
||||
return e.MarshalXMLElement(e, enc, start)
|
||||
}
|
||||
|
||||
func (e *Body) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error {
|
||||
return e.UnmarshalXMLElement(e, dec, start)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user