This commit is contained in:
Mike Farah
2024-03-12 16:43:53 +11:00
parent 836d50ac9f
commit 1c9f001171
40 changed files with 321 additions and 309 deletions
+35 -35
View File
@@ -36,8 +36,8 @@ func (dec *xmlDecoder) Init(reader io.Reader) error {
return nil
}
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yqlib..CandidateNode, error) {
yamlNode := &yqlib..CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yqlib.CandidateNode, error) {
yamlNode := &yqlib.CandidateNode{Kind: yqlib.SequenceNode, Tag: "!!seq"}
for _, child := range nodes {
yamlChild, err := dec.convertToYamlNode(child)
if err != nil {
@@ -64,14 +64,14 @@ func (dec *xmlDecoder) processComment(c string) string {
return replacement
}
func (dec *xmlDecoder) createMap(n *xmlNode) (*yqlib..CandidateNode, error) {
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
yamlNode := &yqlib..CandidateNode{Kind: MappingNode, Tag: "!!map"}
func (dec *xmlDecoder) createMap(n *xmlNode) (*yqlib.CandidateNode, error) {
yqlib.GetLogger().Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
yamlNode := &yqlib.CandidateNode{Kind: yqlib.MappingNode, Tag: "!!map"}
if len(n.Data) > 0 {
log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
yqlib.GetLogger().Debugf("creating content node for map: %v", dec.prefs.ContentName)
label := dec.prefs.ContentName
labelNode := createScalarNode(label, label)
labelNode := yqlib.CreateScalarNode(label, label)
labelNode.HeadComment = dec.processComment(n.HeadComment)
labelNode.LineComment = dec.processComment(n.LineComment)
labelNode.FootComment = dec.processComment(n.FootComment)
@@ -81,19 +81,19 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yqlib..CandidateNode, error) {
for i, keyValuePair := range n.Children {
label := keyValuePair.K
children := keyValuePair.V
labelNode := createScalarNode(label, label)
var valueNode *yqlib..CandidateNode
labelNode := yqlib.CreateScalarNode(label, label)
var valueNode *yqlib.CandidateNode
var err error
if i == 0 {
log.Debugf("head comment here")
yqlib.GetLogger().Debugf("head comment here")
labelNode.HeadComment = dec.processComment(n.HeadComment)
}
log.Debugf("label=%v, i=%v, keyValuePair.FootComment: %v", label, i, keyValuePair.FootComment)
yqlib.GetLogger().Debugf("label=%v, i=%v, keyValuePair.FootComment: %v", label, i, keyValuePair.FootComment)
labelNode.FootComment = dec.processComment(keyValuePair.FootComment)
log.Debug("len of children in %v is %v", label, len(children))
yqlib.GetLogger().Debug("len of children in %v is %v", label, len(children))
if len(children) > 1 {
valueNode, err = dec.createSequence(children)
if err != nil {
@@ -106,7 +106,7 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yqlib..CandidateNode, error) {
if len(children[0].Children) == 0 && children[0].HeadComment != "" {
if len(children[0].Data) > 0 {
log.Debug("scalar comment hack, currentlabel [%v]", labelNode.HeadComment)
yqlib.GetLogger().Debug("scalar comment hack, currentlabel [%v]", labelNode.HeadComment)
labelNode.HeadComment = joinComments([]string{labelNode.HeadComment, strings.TrimSpace(children[0].HeadComment)}, "\n")
children[0].HeadComment = ""
} else {
@@ -126,33 +126,33 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yqlib..CandidateNode, error) {
return yamlNode, nil
}
func (dec *xmlDecoder) createValueNodeFromData(values []string) *yqlib..CandidateNode {
func (dec *xmlDecoder) createValueNodeFromData(values []string) *yqlib.CandidateNode {
switch len(values) {
case 0:
return createScalarNode(nil, "")
return yqlib.CreateScalarNode(nil, "")
case 1:
return createScalarNode(values[0], values[0])
return yqlib.CreateScalarNode(values[0], values[0])
default:
content := make([]*yqlib..CandidateNode, 0)
content := make([]*yqlib.CandidateNode, 0)
for _, value := range values {
content = append(content, createScalarNode(value, value))
content = append(content, yqlib.CreateScalarNode(value, value))
}
return &yqlib..CandidateNode{
Kind: SequenceNode,
return &yqlib.CandidateNode{
Kind: yqlib.SequenceNode,
Tag: "!!seq",
Content: content,
}
}
}
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yqlib..CandidateNode, error) {
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yqlib.CandidateNode, error) {
if len(n.Children) > 0 {
return dec.createMap(n)
}
scalar := dec.createValueNodeFromData(n.Data)
log.Debug("scalar (%v), headC: %v, lineC: %v, footC: %v", scalar.Tag, n.HeadComment, n.LineComment, n.FootComment)
yqlib.GetLogger().Debug("scalar (%v), headC: %v, lineC: %v, footC: %v", scalar.Tag, n.HeadComment, n.LineComment, n.FootComment)
scalar.HeadComment = dec.processComment(n.HeadComment)
scalar.LineComment = dec.processComment(n.LineComment)
if scalar.Tag == "!!seq" {
@@ -165,7 +165,7 @@ func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yqlib..CandidateNode, err
return scalar, nil
}
func (dec *xmlDecoder) Decode() (*yqlib..CandidateNode, error) {
func (dec *xmlDecoder) Decode() (*yqlib.CandidateNode, error) {
if dec.finished {
return nil, io.EOF
}
@@ -212,17 +212,17 @@ func (n *xmlNode) AddChild(s string, c *xmlNode) {
if n.Children == nil {
n.Children = make([]*xmlChildrenKv, 0)
}
log.Debug("looking for %s", s)
yqlib.GetLogger().Debug("looking for %s", s)
// see if we can find an existing entry to add to
for _, childEntry := range n.Children {
if childEntry.K == s {
log.Debug("found it, appending an entry%s", s)
yqlib.GetLogger().Debug("found it, appending an entry%s", s)
childEntry.V = append(childEntry.V, c)
log.Debug("yay len of children in %v is %v", s, len(childEntry.V))
yqlib.GetLogger().Debug("yay len of children in %v is %v", s, len(childEntry.V))
return
}
}
log.Debug("not there, making a new one %s", s)
yqlib.GetLogger().Debug("not there, making a new one %s", s)
n.Children = append(n.Children, &xmlChildrenKv{K: s, V: []*xmlNode{c}})
}
@@ -268,7 +268,7 @@ func (dec *xmlDecoder) decodeXML(root *xmlNode) error {
switch se := t.(type) {
case xml.StartElement:
log.Debug("start element %v", se.Name.Local)
yqlib.GetLogger().Debug("start element %v", se.Name.Local)
elem.state = "started"
// Build new a new current element and link it to its parent
elem = &element{
@@ -297,14 +297,14 @@ func (dec *xmlDecoder) decodeXML(root *xmlNode) error {
if len(newBit) > 0 {
elem.n.Data = append(elem.n.Data, newBit)
elem.state = "chardata"
log.Debug("chardata [%v] for %v", elem.n.Data, elem.label)
yqlib.GetLogger().Debug("chardata [%v] for %v", elem.n.Data, elem.label)
}
case xml.EndElement:
if elem == nil {
log.Debug("no element, probably bad xml")
yqlib.GetLogger().Debug("no element, probably bad xml")
continue
}
log.Debug("end element %v", elem.label)
yqlib.GetLogger().Debug("end element %v", elem.label)
elem.state = "finished"
// And add it to its parent list
if elem.parent != nil {
@@ -320,10 +320,10 @@ func (dec *xmlDecoder) decodeXML(root *xmlNode) error {
applyFootComment(elem, commentStr)
} else if elem.state == "chardata" {
log.Debug("got a line comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
yqlib.GetLogger().Debug("got a line comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
elem.n.LineComment = joinComments([]string{elem.n.LineComment, commentStr}, " ")
} else {
log.Debug("got a head comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
yqlib.GetLogger().Debug("got a head comment for (%v) %v: [%v]", elem.state, elem.label, commentStr)
elem.n.HeadComment = joinComments([]string{elem.n.HeadComment, commentStr}, " ")
}
@@ -348,7 +348,7 @@ func applyFootComment(elem *element, commentStr string) {
if len(elem.n.Children) > 0 {
lastChildIndex := len(elem.n.Children) - 1
childKv := elem.n.Children[lastChildIndex]
log.Debug("got a foot comment, putting on last child for %v: [%v]", childKv.K, commentStr)
yqlib.GetLogger().Debug("got a foot comment, putting on last child for %v: [%v]", childKv.K, commentStr)
// if it's an array of scalars, put the foot comment on the scalar itself
if len(childKv.V) > 0 && len(childKv.V[0].Children) == 0 {
nodeToUpdate := childKv.V[len(childKv.V)-1]
@@ -357,7 +357,7 @@ func applyFootComment(elem *element, commentStr string) {
childKv.FootComment = joinComments([]string{elem.n.FootComment, commentStr}, " ")
}
} else {
log.Debug("got a foot comment for %v: [%v]", elem.label, commentStr)
yqlib.GetLogger().Debug("got a foot comment for %v: [%v]", elem.label, commentStr)
elem.n.FootComment = joinComments([]string{elem.n.FootComment, commentStr}, " ")
}
}
+29 -29
View File
@@ -61,7 +61,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yqlib.CandidateNode) error {
return err
}
if _, err := e.writer.Write([]byte("\n")); err != nil {
log.Warning("Unable to write newline, skipping: %w", err)
yqlib.GetLogger().Warning("Unable to write newline, skipping: %w", err)
}
}
}
@@ -102,7 +102,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yqlib.CandidateNode) error {
}
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yqlib.CandidateNode) error {
err := e.encodeComment(encoder, headAndLineComment(node))
err := e.encodeComment(encoder, node.CleanHeadAndLineComment())
if err != nil {
return err
}
@@ -111,12 +111,12 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yqlib.Candida
value := node.Content[i+1]
start := xml.StartElement{Name: xml.Name{Local: key.Value}}
log.Debugf("comments of key %v", key.Value)
err := e.encodeComment(encoder, headAndLineComment(key))
yqlib.GetLogger().Debugf("comments of key %v", key.Value)
err := e.encodeComment(encoder, key.CleanHeadAndLineComment())
if err != nil {
return err
}
if headAndLineComment(key) != "" {
if key.CleanHeadAndLineComment() != "" {
var newLine xml.CharData = []byte("\n")
err = encoder.EncodeToken(newLine)
if err != nil {
@@ -133,7 +133,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yqlib.Candida
return err
}
if _, err := e.writer.Write([]byte("\n")); err != nil {
log.Warning("Unable to write newline, skipping: %w", err)
yqlib.GetLogger().Warning("Unable to write newline, skipping: %w", err)
}
} else if key.Value == e.prefs.DirectiveName {
var directive xml.Directive = []byte(value.Value)
@@ -141,23 +141,23 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yqlib.Candida
return err
}
if _, err := e.writer.Write([]byte("\n")); err != nil {
log.Warning("Unable to write newline, skipping: %w", err)
yqlib.GetLogger().Warning("Unable to write newline, skipping: %w", err)
}
} else {
log.Debugf("recursing")
yqlib.GetLogger().Debugf("recursing")
err = e.doEncode(encoder, value, start)
if err != nil {
return err
}
}
err = e.encodeComment(encoder, footComment(key))
err = e.encodeComment(encoder, key.CleanFootComment())
if err != nil {
return err
}
}
return e.encodeComment(encoder, footComment(node))
return e.encodeComment(encoder, node.CleanFootComment())
}
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
@@ -165,7 +165,7 @@ func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yqlib.CandidateNode
if err != nil {
return err
}
return e.encodeComment(encoder, headComment(node))
return e.encodeComment(encoder, node.CleanHeadComment())
}
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
@@ -173,16 +173,16 @@ func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yqlib.CandidateNode,
if err != nil {
return err
}
return e.encodeComment(encoder, footComment(node))
return e.encodeComment(encoder, node.CleanFootComment())
}
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
switch node.Kind {
case MappingNode:
case yqlib.MappingNode:
return e.encodeMap(encoder, node, start)
case SequenceNode:
case yqlib.SequenceNode:
return e.encodeArray(encoder, node, start)
case ScalarNode:
case yqlib.ScalarNode:
err := e.encodeStart(encoder, node, start)
if err != nil {
return err
@@ -194,7 +194,7 @@ func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yqlib.CandidateNode, s
return err
}
if err = e.encodeComment(encoder, lineComment(node)); err != nil {
if err = e.encodeComment(encoder, node.CleanLineComment()); err != nil {
return err
}
@@ -209,13 +209,13 @@ var chompRegexp = regexp.MustCompile(`\n$`)
func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) error {
if commentStr != "" {
log.Debugf("got comment [%v]", commentStr)
yqlib.GetLogger().Debugf("got comment [%v]", commentStr)
// multi line string
if len(commentStr) > 2 && strings.Contains(commentStr[1:len(commentStr)-1], "\n") {
commentStr = chompRegexp.ReplaceAllString(commentStr, "")
log.Debugf("chompRegexp [%v]", commentStr)
yqlib.GetLogger().Debugf("chompRegexp [%v]", commentStr)
commentStr = xmlEncodeMultilineCommentRegex.ReplaceAllString(commentStr, "$1$2")
log.Debugf("processed multiline [%v]", commentStr)
yqlib.GetLogger().Debugf("processed multiline [%v]", commentStr)
// if the first line is non blank, add a space
if commentStr[0] != '\n' && commentStr[0] != ' ' {
commentStr = " " + commentStr
@@ -227,9 +227,9 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
if !strings.HasSuffix(commentStr, " ") && !strings.HasSuffix(commentStr, "\n") {
commentStr = commentStr + " "
log.Debugf("added suffix [%v]", commentStr)
yqlib.GetLogger().Debugf("added suffix [%v]", commentStr)
}
log.Debugf("encoding comment [%v]", commentStr)
yqlib.GetLogger().Debugf("encoding comment [%v]", commentStr)
var comment xml.Comment = []byte(commentStr)
err := encoder.EncodeToken(comment)
@@ -242,7 +242,7 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
if err := e.encodeComment(encoder, node.CleanHeadAndLineComment()); err != nil {
return err
}
@@ -252,7 +252,7 @@ func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yqlib.CandidateNode
return err
}
}
return e.encodeComment(encoder, footComment(node))
return e.encodeComment(encoder, node.CleanFootComment())
}
func (e *xmlEncoder) isAttribute(name string) bool {
@@ -263,7 +263,7 @@ func (e *xmlEncoder) isAttribute(name string) bool {
}
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
log.Debug("its a map")
yqlib.GetLogger().Debug("its a map")
//first find all the attributes and put them on the start token
for i := 0; i < len(node.Content); i += 2 {
@@ -271,7 +271,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yqlib.CandidateNode,
value := node.Content[i+1]
if e.isAttribute(key.Value) {
if value.Kind == ScalarNode {
if value.Kind == yqlib.ScalarNode {
attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1)
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value})
} else {
@@ -290,7 +290,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yqlib.CandidateNode,
key := node.Content[i]
value := node.Content[i+1]
err := e.encodeComment(encoder, headAndLineComment(key))
err := e.encodeComment(encoder, key.CleanHeadAndLineComment())
if err != nil {
return err
}
@@ -307,7 +307,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yqlib.CandidateNode,
}
} else if key.Value == e.prefs.ContentName {
// directly encode the contents
err = e.encodeComment(encoder, headAndLineComment(value))
err = e.encodeComment(encoder, value.CleanHeadAndLineComment())
if err != nil {
return err
}
@@ -316,7 +316,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yqlib.CandidateNode,
if err != nil {
return err
}
err = e.encodeComment(encoder, footComment(value))
err = e.encodeComment(encoder, value.CleanFootComment())
if err != nil {
return err
}
@@ -327,7 +327,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yqlib.CandidateNode,
return err
}
}
err = e.encodeComment(encoder, footComment(key))
err = e.encodeComment(encoder, key.CleanFootComment())
if err != nil {
return err
}
+11 -6
View File
@@ -47,17 +47,22 @@ func (p *XmlPreferences) Copy() XmlPreferences {
var ConfiguredXMLPreferences = NewDefaultXmlPreferences()
var XMLFormat = &yqlib.Format{"xml", []string{"x"},
var XMLFormat = &yqlib.Format{"xml", []string{"x"}, "xml",
func() yqlib.Encoder { return NewXMLEncoder(ConfiguredXMLPreferences) },
func() yqlib.Decoder { return NewXMLDecoder(ConfiguredXMLPreferences) },
func(indent int) yqlib.Encoder {
prefs := ConfiguredXMLPreferences.Copy()
prefs.Indent = indent
return NewXMLEncoder(prefs)
},
}
var xmlYqRules = []*yqlib.ParticipleYqRule{
{"XMLEncodeWithIndent", `to_?xml\([0-9]+\)`, encodeParseIndent(XMLFormat), 0},
{"XmlDecode", `from_?xml|@xmld`, decodeOp(XMLFormat), 0},
{"XMLEncode", `to_?xml`, encodeWithIndent(XMLFormat, 2), 0},
{"XMLEncodeNoIndent", `@xml`, encodeWithIndent(XMLFormat, 0), 0},
{"LoadXML", `load_?xml|xml_?load`, loadOp(NewXMLDecoder(ConfiguredXMLPreferences), false), 0},
{"XMLEncodeWithIndent", `to_?xml\([0-9]+\)`, yqlib.CreateEncodeYqActionParsingIndent(XMLFormat), 0},
{"XmlDecode", `from_?xml|@xmld`, yqlib.CreateDecodeOpYqAction(XMLFormat), 0},
{"XMLEncode", `to_?xml`, yqlib.CreateEncodeOpYqAction(XMLFormat, 2), 0},
{"XMLEncodeNoIndent", `@xml`, yqlib.CreateEncodeOpYqAction(XMLFormat, 0), 0},
{"LoadXML", `load_?xml|xml_?load`, yqlib.CreateLoadOpYqAction(NewXMLDecoder(ConfiguredXMLPreferences)), 0},
}
func RegisterXmlFormat() {