feat(ipub,ast)!: BaseElement marshaller

This commit is contained in:
Guz
2025-05-20 10:11:27 -03:00
parent 87e7a74dd3
commit 294513a772
4 changed files with 84 additions and 6 deletions

View File

@@ -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)

View File

@@ -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
View 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
}

View File

@@ -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)
}