Can handle xml directives

This commit is contained in:
Mike Farah 2022-10-18 14:33:57 +11:00
parent c1b333b2c2
commit 6bbab2a664
3 changed files with 30 additions and 12 deletions

View File

@ -1,6 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" > <!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
<apple> <apple>
Cats are cgreat <?coolioo version="1.0"?>
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
<b>things</b> <b>things</b>
</apple> </apple>

View File

@ -15,7 +15,7 @@ type xmlDecoder struct {
reader io.Reader reader io.Reader
readAnything bool readAnything bool
attributePrefix string attributePrefix string
directivePrefix string directiveName string
procInstPrefix string procInstPrefix string
contentName string contentName string
strictMode bool strictMode bool
@ -35,7 +35,7 @@ func NewXMLDecoder(attributePrefix string, contentName string, strictMode bool,
strictMode: strictMode, strictMode: strictMode,
keepNamespace: keepNamespace, keepNamespace: keepNamespace,
useRawToken: useRawToken, useRawToken: useRawToken,
directivePrefix: "_directive_", directiveName: "_directive_",
procInstPrefix: "_procInst_", procInstPrefix: "_procInst_",
} }
} }
@ -286,6 +286,8 @@ func (dec *xmlDecoder) decodeXML(root *xmlNode) error {
case xml.ProcInst: case xml.ProcInst:
elem.n.AddChild(dec.procInstPrefix+se.Target, &xmlNode{Data: string(se.Inst)}) elem.n.AddChild(dec.procInstPrefix+se.Target, &xmlNode{Data: string(se.Inst)})
case xml.Directive:
elem.n.AddChild(dec.directiveName, &xmlNode{Data: string(se)})
} }
} }

View File

@ -15,8 +15,9 @@ type xmlEncoder struct {
attributePrefix string attributePrefix string
contentName string contentName string
indentString string indentString string
directivePrefix string directiveName string
procInstPrefix string procInstPrefix string
writer io.Writer
} }
func NewXMLEncoder(indent int, attributePrefix string, contentName string) Encoder { func NewXMLEncoder(indent int, attributePrefix string, contentName string) Encoder {
@ -25,7 +26,7 @@ func NewXMLEncoder(indent int, attributePrefix string, contentName string) Encod
for index := 0; index < indent; index++ { for index := 0; index < indent; index++ {
indentString = indentString + " " indentString = indentString + " "
} }
return &xmlEncoder{attributePrefix, contentName, indentString, "_directive_", "_procInst_"} return &xmlEncoder{attributePrefix, contentName, indentString, "_directive_", "_procInst_", nil}
} }
func (e *xmlEncoder) CanHandleAliases() bool { func (e *xmlEncoder) CanHandleAliases() bool {
@ -42,11 +43,13 @@ func (e *xmlEncoder) PrintLeadingContent(writer io.Writer, content string) error
func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error { func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
encoder := xml.NewEncoder(writer) encoder := xml.NewEncoder(writer)
// hack so we can manually add newlines to procInst and directives
e.writer = writer
encoder.Indent("", e.indentString) encoder.Indent("", e.indentString)
switch node.Kind { switch node.Kind {
case yaml.MappingNode: case yaml.MappingNode:
err := e.encodeTopLevelMap(encoder, node, writer) err := e.encodeTopLevelMap(encoder, node)
if err != nil { if err != nil {
return err return err
} }
@ -55,7 +58,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
if err != nil { if err != nil {
return err return err
} }
err = e.encodeTopLevelMap(encoder, unwrapDoc(node), writer) err = e.encodeTopLevelMap(encoder, unwrapDoc(node))
if err != nil { if err != nil {
return err return err
} }
@ -78,7 +81,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
} }
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node, writer io.Writer) error { func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) error {
err := e.encodeComment(encoder, headAndLineComment(node)) err := e.encodeComment(encoder, headAndLineComment(node))
if err != nil { if err != nil {
return err return err
@ -94,13 +97,21 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node, wr
return err return err
} }
if strings.HasPrefix(key.Value, e.procInstPrefix) && key.Value != e.contentName { if strings.HasPrefix(key.Value, e.procInstPrefix) {
name := strings.Replace(key.Value, e.procInstPrefix, "", 1) name := strings.Replace(key.Value, e.procInstPrefix, "", 1)
procInst := xml.ProcInst{Target: name, Inst: []byte(value.Value)} procInst := xml.ProcInst{Target: name, Inst: []byte(value.Value)}
if err := encoder.EncodeToken(procInst); err != nil { if err := encoder.EncodeToken(procInst); err != nil {
return err return err
} }
if _, err := writer.Write([]byte("\n")); err != nil { if _, err := e.writer.Write([]byte("\n")); err != nil {
log.Warning("Unable to write newline, skipping: %w", err)
}
} else if key.Value == e.directiveName {
var directive xml.Directive = []byte(value.Value)
if err := encoder.EncodeToken(directive); err != nil {
return err
}
if _, err := e.writer.Write([]byte("\n")); err != nil {
log.Warning("Unable to write newline, skipping: %w", err) log.Warning("Unable to write newline, skipping: %w", err)
} }
} else { } else {
@ -226,13 +237,17 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.
if err != nil { if err != nil {
return err return err
} }
if strings.HasPrefix(key.Value, e.procInstPrefix) && key.Value != e.contentName { if strings.HasPrefix(key.Value, e.procInstPrefix) {
name := strings.Replace(key.Value, e.procInstPrefix, "", 1) name := strings.Replace(key.Value, e.procInstPrefix, "", 1)
procInst := xml.ProcInst{Target: name, Inst: []byte(value.Value)} procInst := xml.ProcInst{Target: name, Inst: []byte(value.Value)}
if err := encoder.EncodeToken(procInst); err != nil { if err := encoder.EncodeToken(procInst); err != nil {
return err return err
} }
} else if key.Value == e.directiveName {
var directive xml.Directive = []byte(value.Value)
if err := encoder.EncodeToken(directive); err != nil {
return err
}
} else if !strings.HasPrefix(key.Value, e.attributePrefix) && key.Value != e.contentName { } else if !strings.HasPrefix(key.Value, e.attributePrefix) && key.Value != e.contentName {
start := xml.StartElement{Name: xml.Name{Local: key.Value}} start := xml.StartElement{Name: xml.Name{Local: key.Value}}
err := e.doEncode(encoder, value, start) err := e.doEncode(encoder, value, start)