diff --git a/pkg/yqlib/decoder_xml.go b/pkg/yqlib/decoder_xml.go
index 3c0e5451..bdb56a49 100644
--- a/pkg/yqlib/decoder_xml.go
+++ b/pkg/yqlib/decoder_xml.go
@@ -63,14 +63,14 @@ func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yaml.Node, error) {
func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
log.Debug("createMap: headC: %v, footC: %v", n.HeadComment, n.FootComment)
- yamlNode := &yaml.Node{Kind: yaml.MappingNode, HeadComment: n.HeadComment}
+ yamlNode := &yaml.Node{Kind: yaml.MappingNode, HeadComment: n.HeadComment, FootComment: n.FootComment}
if len(n.Data) > 0 {
label := dec.contentPrefix
yamlNode.Content = append(yamlNode.Content, createScalarNode(label, label), createScalarNode(n.Data, n.Data))
}
- for i, keyValuePair := range n.Children {
+ for _, keyValuePair := range n.Children {
label := keyValuePair.K
children := keyValuePair.V
labelNode := createScalarNode(label, label)
@@ -88,9 +88,6 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
if err != nil {
return nil, err
}
- if i == len(n.Children)-1 {
- valueNode.FootComment = n.FootComment
- }
}
yamlNode.Content = append(yamlNode.Content, labelNode, valueNode)
}
@@ -105,6 +102,7 @@ func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yaml.Node, error) {
scalar := createScalarNode(n.Data, n.Data)
log.Debug("scalar headC: %v, footC: %v", n.HeadComment, n.FootComment)
scalar.LineComment = n.HeadComment
+ scalar.FootComment = n.FootComment
return scalar, nil
}
@@ -221,10 +219,21 @@ func (dec *xmlDecoder) decodeXml(root *xmlNode) error {
elem = elem.parent
case xml.Comment:
- commentStr := trimNonGraphic(string(xml.CharData(se)))
+ commentStr := string(xml.CharData(se))
if elem.state == "started" {
log.Debug("got a foot comment for %v: %v", elem.label, commentStr)
- elem.n.FootComment = commentStr
+ // elem.n.FootComment = elem.n.FootComment + commentStr
+ // put the comment on the foot of the last child
+ if len(elem.n.Children) > 0 {
+
+ child := elem.n.Children[len(elem.n.Children)-1]
+ log.Debug("putting it here: %v", child.K)
+ child.V[0].FootComment = child.V[0].FootComment + commentStr
+ } else {
+ log.Debug("putting it on the element")
+ elem.n.FootComment = elem.n.FootComment + commentStr
+ }
+
} else {
log.Debug("got a head comment for %v: %v", elem.label, commentStr)
elem.n.HeadComment = joinFilter([]string{elem.n.HeadComment, commentStr})
diff --git a/pkg/yqlib/doc/usage/xml.md b/pkg/yqlib/doc/usage/xml.md
index f3a31666..2f424cba 100644
--- a/pkg/yqlib/doc/usage/xml.md
+++ b/pkg/yqlib/doc/usage/xml.md
@@ -22,224 +22,6 @@ XML nodes that have attributes then plain content, e.g:
The content of the node will be set as a field in the map with the key "+content". Use the `--xml-content-name` flag to change this.
-## Parse xml: simple
-Given a sample.xml file of:
-```xml
-
-meow
-```
-then
-```bash
-yq e -p=xml '.' sample.xml
-```
-will output
-```yaml
-cat: meow
-```
-
-## Parse xml: array
-Consecutive nodes with identical xml names are assumed to be arrays.
-
-Given a sample.xml file of:
-```xml
-
-1
-2
-```
-then
-```bash
-yq e -p=xml '.' sample.xml
-```
-will output
-```yaml
-animal:
- - "1"
- - "2"
-```
-
-## Parse xml: attributes
-Attributes are converted to fields, with the attribute prefix.
-
-Given a sample.xml file of:
-```xml
-
-
- 7
-
-```
-then
-```bash
-yq e -p=xml '.' sample.xml
-```
-will output
-```yaml
-cat:
- +legs: "4"
- legs: "7"
-```
-
-## Parse xml: attributes with content
-Content is added as a field, using the content name
-
-Given a sample.xml file of:
-```xml
-
-meow
-```
-then
-```bash
-yq e -p=xml '.' sample.xml
-```
-will output
-```yaml
-cat:
- +content: meow
- +legs: "4"
-```
-
-## Parse xml: with comments
-A best attempt is made to preserve comments.
-
-Given a sample.xml file of:
-```xml
-
-
-
-
- 3
-
-
- 4
-
-
-
-
-
-
-```
-then
-```bash
-yq e -p=xml '.' sample.xml
-```
-will output
-```yaml
-# before cat
-cat:
- # in cat before
- x: "3" # multi
- # line comment
- # for x
- y:
- # in y before
- d: "4" # in d before in d after
- # in y after
-
-# after cat
-```
-
-## Encode xml: simple
-Given a sample.yml file of:
-```yaml
-cat: purrs
-```
-then
-```bash
-yq e -o=xml '.' sample.yml
-```
-will output
-```xml
-purrs
-```
-
-## Encode xml: array
-Given a sample.yml file of:
-```yaml
-pets:
- cat:
- - purrs
- - meows
-```
-then
-```bash
-yq e -o=xml '.' sample.yml
-```
-will output
-```xml
-
- purrs
- meows
-
-```
-
-## Encode xml: attributes
-Fields with the matching xml-attribute-prefix are assumed to be attributes.
-
-Given a sample.yml file of:
-```yaml
-cat:
- +name: tiger
- meows: true
-
-```
-then
-```bash
-yq e -o=xml '.' sample.yml
-```
-will output
-```xml
-
- true
-
-```
-
-## Encode xml: attributes with content
-Fields with the matching xml-content-name is assumed to be content.
-
-Given a sample.yml file of:
-```yaml
-cat:
- +name: tiger
- +content: cool
-
-```
-then
-```bash
-yq e -o=xml '.' sample.yml
-```
-will output
-```xml
-cool
-```
-
-## Encode xml: comments
-A best attempt is made to copy comments to xml.
-
-Given a sample.yml file of:
-```yaml
-# above_cat
-cat: # inline_cat
- # above_array
- array: # inline_array
- - val1 # inline_val1
- # above_val2
- - val2 # inline_val2
-# below_cat
-
-```
-then
-```bash
-yq e -o=xml '.' sample.yml
-```
-will output
-```xml
-
- val1
- val2
-
-```
-
## Round trip: with comments
A best effort is made, but comment positions and white space are not preserved perfectly.
@@ -252,6 +34,7 @@ Given a sample.xml file of:
3
+
4
@@ -268,17 +51,19 @@ yq e -p=xml '.' sample.xml
```
will output
```yaml
-# before cat
+# before cat
cat:
- # in cat before
- x: "3" # multi
+ # in cat before
+ x: "3" # multi
# line comment
- # for x
- y:
- # in y before
- d: "4" # in d before in d after
- # in y after
+ # for x
+ # before y
-# after cat
+ y:
+ # in y before
+ d: "4" # in d before in d after
+ # in y after
+
+# after cat
```
diff --git a/pkg/yqlib/encoder_xml.go b/pkg/yqlib/encoder_xml.go
index 329c57fa..12b3e547 100644
--- a/pkg/yqlib/encoder_xml.go
+++ b/pkg/yqlib/encoder_xml.go
@@ -49,11 +49,12 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
return err
}
case yaml.DocumentNode:
+ log.Debugf("ENCODING DOCUMENT NODE")
err := e.encodeComment(encoder, headAndLineComment(node))
if err != nil {
return err
}
- // this used to call encode...
+ log.Debugf("OK NOW THE ACTUAL")
err = e.encodeTopLevelMap(encoder, unwrapDoc(node))
if err != nil {
return err
@@ -78,16 +79,23 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
}
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) error {
+ err := e.encodeComment(encoder, headAndLineComment(node))
+ if err != nil {
+ return err
+ }
for i := 0; i < len(node.Content); i += 2 {
key := node.Content[i]
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))
if err != nil {
return err
}
+ log.Debugf("recursing")
+
err = e.doEncode(encoder, value, start)
if err != nil {
return err
@@ -97,7 +105,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) er
return err
}
}
- return nil
+ return e.encodeComment(encoder, footComment(node))
}
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
@@ -141,6 +149,7 @@ func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yaml.Node, start xml.S
func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) error {
if commentStr != "" {
+ log.Debugf("encoding comment %v", commentStr)
var comment xml.Comment = []byte(commentStr)
err := encoder.EncodeToken(comment)
if err != nil {
@@ -151,6 +160,7 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
}
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
+ e.encodeComment(encoder, headAndLineComment(node))
for i := 0; i < len(node.Content); i++ {
value := node.Content[i]
err := e.doEncode(encoder, value, start.Copy())
@@ -158,10 +168,12 @@ func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yaml.Node, start xm
return err
}
}
+ e.encodeComment(encoder, footComment(node))
return nil
}
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
+ log.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 {
@@ -201,11 +213,19 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.
}
} else if key.Value == e.contentName {
// directly encode the contents
+ err = e.encodeComment(encoder, headAndLineComment(value))
+ if err != nil {
+ return err
+ }
var charData xml.CharData = []byte(value.Value)
err = encoder.EncodeToken(charData)
if err != nil {
return err
}
+ err = e.encodeComment(encoder, footComment(value))
+ if err != nil {
+ return err
+ }
}
err = e.encodeComment(encoder, footComment(key))
if err != nil {
diff --git a/pkg/yqlib/printer.go b/pkg/yqlib/printer.go
index 82517414..534dbfd7 100644
--- a/pkg/yqlib/printer.go
+++ b/pkg/yqlib/printer.go
@@ -100,7 +100,6 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
}
if p.firstTimePrinting {
- log.Debugf("its my first time *blush*")
node := matchingNodes.Front().Value.(*CandidateNode)
p.previousDocIndex = node.Document
p.previousFileIndex = node.FileIndex
diff --git a/pkg/yqlib/xml_test.go b/pkg/yqlib/xml_test.go
index 72de0fa6..6ea23e56 100644
--- a/pkg/yqlib/xml_test.go
+++ b/pkg/yqlib/xml_test.go
@@ -65,6 +65,7 @@ var inputXmlWithComments = `
3
+
4
@@ -89,14 +90,14 @@ cat:
# after cat
`
-var expectedRoundtripXmlWithComments = `
-
+ 3
-
- 4
-
-
+for x -->3
+
+ 4
+
+
`
var yamlWithComments = `# above_cat
@@ -116,75 +117,75 @@ var expectedXmlWithComments = `