This commit is contained in:
Mike Farah 2023-04-08 19:56:35 +10:00
parent 52b364ec52
commit 66ab916c6b
14 changed files with 92 additions and 111 deletions

View File

@ -12,7 +12,6 @@ import (
"unicode" "unicode"
"golang.org/x/net/html/charset" "golang.org/x/net/html/charset"
yaml "gopkg.in/yaml.v3"
) )
type xmlDecoder struct { type xmlDecoder struct {
@ -36,8 +35,8 @@ func (dec *xmlDecoder) Init(reader io.Reader) error {
return nil return nil
} }
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yaml.Node, error) { func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*CandidateNode, error) {
yamlNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"} yamlNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
for _, child := range nodes { for _, child := range nodes {
yamlChild, err := dec.convertToYamlNode(child) yamlChild, err := dec.convertToYamlNode(child)
if err != nil { if err != nil {
@ -64,9 +63,9 @@ func (dec *xmlDecoder) processComment(c string) string {
return replacement return replacement
} }
func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) { func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment) log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
yamlNode := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"} yamlNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
if len(n.Data) > 0 { if len(n.Data) > 0 {
log.Debugf("creating content node for map: %v", dec.prefs.ContentName) log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
@ -82,7 +81,7 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
label := keyValuePair.K label := keyValuePair.K
children := keyValuePair.V children := keyValuePair.V
labelNode := createScalarNode(label, label) labelNode := createScalarNode(label, label)
var valueNode *yaml.Node var valueNode *CandidateNode
var err error var err error
if i == 0 { if i == 0 {
@ -126,26 +125,26 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
return yamlNode, nil return yamlNode, nil
} }
func (dec *xmlDecoder) createValueNodeFromData(values []string) *yaml.Node { func (dec *xmlDecoder) createValueNodeFromData(values []string) *CandidateNode {
switch len(values) { switch len(values) {
case 0: case 0:
return createScalarNode(nil, "") return createScalarNode(nil, "")
case 1: case 1:
return createScalarNode(values[0], values[0]) return createScalarNode(values[0], values[0])
default: default:
content := make([]*yaml.Node, 0) content := make([]*CandidateNode, 0)
for _, value := range values { for _, value := range values {
content = append(content, createScalarNode(value, value)) content = append(content, createScalarNode(value, value))
} }
return &yaml.Node{ return &CandidateNode{
Kind: yaml.SequenceNode, Kind: SequenceNode,
Tag: "!!seq", Tag: "!!seq",
Content: content, Content: content,
} }
} }
} }
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yaml.Node, error) { func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*CandidateNode, error) {
if len(n.Children) > 0 { if len(n.Children) > 0 {
return dec.createMap(n) return dec.createMap(n)
} }
@ -190,10 +189,8 @@ func (dec *xmlDecoder) Decode() (*CandidateNode, error) {
dec.finished = true dec.finished = true
return &CandidateNode{ return &CandidateNode{
Node: &yaml.Node{ Kind: DocumentNode,
Kind: yaml.DocumentNode, Content: []*CandidateNode{firstNode},
Content: []*yaml.Node{firstNode},
},
}, nil }, nil
} }

View File

@ -2,20 +2,18 @@ package yqlib
import ( import (
"io" "io"
yaml "gopkg.in/yaml.v3"
) )
type Encoder interface { type Encoder interface {
Encode(writer io.Writer, node *yaml.Node) error Encode(writer io.Writer, node *CandidateNode) error
PrintDocumentSeparator(writer io.Writer) error PrintDocumentSeparator(writer io.Writer) error
PrintLeadingContent(writer io.Writer, content string) error PrintLeadingContent(writer io.Writer, content string) error
CanHandleAliases() bool CanHandleAliases() bool
} }
func mapKeysToStrings(node *yaml.Node) { func mapKeysToStrings(node *CandidateNode) {
if node.Kind == yaml.MappingNode { if node.Kind == MappingNode {
for index, child := range node.Content { for index, child := range node.Content {
if index%2 == 0 { // its a map key if index%2 == 0 { // its a map key
child.Tag = "!!str" child.Tag = "!!str"

View File

@ -4,8 +4,6 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io" "io"
yaml "gopkg.in/yaml.v3"
) )
type base64Encoder struct { type base64Encoder struct {
@ -28,9 +26,9 @@ func (e *base64Encoder) PrintLeadingContent(writer io.Writer, content string) er
return nil return nil
} }
func (e *base64Encoder) Encode(writer io.Writer, originalNode *yaml.Node) error { func (e *base64Encoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
node := unwrapDoc(originalNode) node := originalNode.unwrapDocument()
if guessTagFromCustomType(node) != "!!str" { if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as base64, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag) return fmt.Errorf("cannot encode %v as base64, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
} }
_, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(originalNode.Value)))) _, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(originalNode.Value))))

View File

@ -4,8 +4,6 @@ import (
"encoding/csv" "encoding/csv"
"fmt" "fmt"
"io" "io"
yaml "gopkg.in/yaml.v3"
) )
type csvEncoder struct { type csvEncoder struct {
@ -89,7 +87,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNo
} }
for i, child := range content { for i, child := range content {
if child.Kind != yaml.MappingNode { if child.Kind != MappingNode {
return fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[%v] is a %v", i, child.Tag) return fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[%v] is a %v", i, child.Tag)
} }
row := e.createChildRow(child, headers) row := e.createChildRow(child, headers)
@ -103,7 +101,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNo
} }
func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error { func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
if originalNode.Kind == yaml.ScalarNode { if originalNode.Kind == ScalarNode {
return writeString(writer, originalNode.Value+"\n") return writeString(writer, originalNode.Value+"\n")
} }
@ -111,17 +109,17 @@ func (e *csvEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error
csvWriter.Comma = e.separator csvWriter.Comma = e.separator
// node must be a sequence // node must be a sequence
node := unwrapDoc(originalNode) node := originalNode.unwrapDocument()
if node.Kind != yaml.SequenceNode { if node.Kind != SequenceNode {
return fmt.Errorf("csv encoding only works for arrays, got: %v", node.Tag) return fmt.Errorf("csv encoding only works for arrays, got: %v", node.Tag)
} else if len(node.Content) == 0 { } else if len(node.Content) == 0 {
return nil return nil
} }
if node.Content[0].Kind == yaml.ScalarNode { if node.Content[0].Kind == ScalarNode {
return e.encodeRow(csvWriter, node.Content) return e.encodeRow(csvWriter, node.Content)
} }
if node.Content[0].Kind == yaml.MappingNode { if node.Content[0].Kind == MappingNode {
return e.encodeObjects(csvWriter, node.Content) return e.encodeObjects(csvWriter, node.Content)
} }

View File

@ -7,7 +7,6 @@ import (
"io" "io"
"github.com/goccy/go-json" "github.com/goccy/go-json"
yaml "gopkg.in/yaml.v3"
) )
type jsonEncoder struct { type jsonEncoder struct {
@ -38,9 +37,9 @@ func (je *jsonEncoder) PrintLeadingContent(writer io.Writer, content string) err
return nil return nil
} }
func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error { func (je *jsonEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == yaml.ScalarNode && je.UnwrapScalar { if node.Kind == ScalarNode && je.UnwrapScalar {
return writeString(writer, node.Value+"\n") return writeString(writer, node.Value+"\n")
} }
@ -58,6 +57,7 @@ func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {
// firstly, convert all map keys to strings // firstly, convert all map keys to strings
mapKeysToStrings(node) mapKeysToStrings(node)
errorDecoding := node.Decode(&dataBucket) errorDecoding := node.Decode(&dataBucket)
if errorDecoding != nil { if errorDecoding != nil {
return errorDecoding return errorDecoding
} }

View File

@ -8,7 +8,6 @@ import (
"strings" "strings"
"github.com/magiconair/properties" "github.com/magiconair/properties"
yaml "gopkg.in/yaml.v3"
) )
type propertiesEncoder struct { type propertiesEncoder struct {
@ -62,9 +61,9 @@ func (pe *propertiesEncoder) PrintLeadingContent(writer io.Writer, content strin
return nil return nil
} }
func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error { func (pe *propertiesEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == yaml.ScalarNode { if node.Kind == ScalarNode {
return writeString(writer, node.Value+"\n") return writeString(writer, node.Value+"\n")
} }
@ -79,7 +78,7 @@ func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
return err return err
} }
func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node, path string, keyNode *yaml.Node) error { func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateNode, path string, keyNode *CandidateNode) error {
comments := "" comments := ""
if keyNode != nil { if keyNode != nil {
@ -91,7 +90,7 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
p.SetComments(path, strings.Split(commentsWithSpaces, "\n")) p.SetComments(path, strings.Split(commentsWithSpaces, "\n"))
switch node.Kind { switch node.Kind {
case yaml.ScalarNode: case ScalarNode:
var nodeValue string var nodeValue string
if pe.unwrapScalar || !strings.Contains(node.Value, " ") { if pe.unwrapScalar || !strings.Contains(node.Value, " ") {
nodeValue = node.Value nodeValue = node.Value
@ -100,13 +99,13 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
} }
_, _, err := p.Set(path, nodeValue) _, _, err := p.Set(path, nodeValue)
return err return err
case yaml.DocumentNode: case DocumentNode:
return pe.doEncode(p, node.Content[0], path, node) return pe.doEncode(p, node.Content[0], path, node)
case yaml.SequenceNode: case SequenceNode:
return pe.encodeArray(p, node.Content, path) return pe.encodeArray(p, node.Content, path)
case yaml.MappingNode: case MappingNode:
return pe.encodeMap(p, node.Content, path) return pe.encodeMap(p, node.Content, path)
case yaml.AliasNode: case AliasNode:
return pe.doEncode(p, node.Alias, path, nil) return pe.doEncode(p, node.Alias, path, nil)
default: default:
return fmt.Errorf("Unsupported node %v", node.Tag) return fmt.Errorf("Unsupported node %v", node.Tag)
@ -120,7 +119,7 @@ func (pe *propertiesEncoder) appendPath(path string, key interface{}) string {
return fmt.Sprintf("%v.%v", path, key) return fmt.Sprintf("%v.%v", path, key)
} }
func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.Node, path string) error { func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*CandidateNode, path string) error {
for index, child := range kids { for index, child := range kids {
err := pe.doEncode(p, child, pe.appendPath(path, index), nil) err := pe.doEncode(p, child, pe.appendPath(path, index), nil)
if err != nil { if err != nil {
@ -130,7 +129,7 @@ func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.
return nil return nil
} }
func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*yaml.Node, path string) error { func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*CandidateNode, path string) error {
for index := 0; index < len(kids); index = index + 2 { for index := 0; index < len(kids); index = index + 2 {
key := kids[index] key := kids[index]
value := kids[index+1] value := kids[index+1]

View File

@ -5,8 +5,6 @@ import (
"io" "io"
"regexp" "regexp"
"strings" "strings"
yaml "gopkg.in/yaml.v3"
) )
var unsafeChars = regexp.MustCompile(`[^\w@%+=:,./-]`) var unsafeChars = regexp.MustCompile(`[^\w@%+=:,./-]`)
@ -31,9 +29,9 @@ func (e *shEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil return nil
} }
func (e *shEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error { func (e *shEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
node := unwrapDoc(originalNode) node := originalNode.unwrapDocument()
if guessTagFromCustomType(node) != "!!str" { if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag) return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
} }

View File

@ -3,8 +3,6 @@ package yqlib
import ( import (
"fmt" "fmt"
"io" "io"
yaml "gopkg.in/yaml.v3"
) )
type tomlEncoder struct { type tomlEncoder struct {
@ -14,8 +12,8 @@ func NewTomlEncoder() Encoder {
return &tomlEncoder{} return &tomlEncoder{}
} }
func (te *tomlEncoder) Encode(writer io.Writer, node *yaml.Node) error { func (te *tomlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == yaml.ScalarNode { if node.Kind == ScalarNode {
return writeString(writer, node.Value+"\n") return writeString(writer, node.Value+"\n")
} }
return fmt.Errorf("only scalars (e.g. strings, numbers, booleans) are supported for TOML output at the moment. Please use yaml output format (-oy) until the encoder has been fully implemented") return fmt.Errorf("only scalars (e.g. strings, numbers, booleans) are supported for TOML output at the moment. Please use yaml output format (-oy) until the encoder has been fully implemented")

View File

@ -4,8 +4,6 @@ import (
"fmt" "fmt"
"io" "io"
"net/url" "net/url"
yaml "gopkg.in/yaml.v3"
) )
type uriEncoder struct { type uriEncoder struct {
@ -27,9 +25,9 @@ func (e *uriEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil return nil
} }
func (e *uriEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error { func (e *uriEncoder) Encode(writer io.Writer, originalNode *CandidateNode) error {
node := unwrapDoc(originalNode) node := originalNode.unwrapDocument()
if guessTagFromCustomType(node) != "!!str" { if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag) return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
} }
_, err := writer.Write([]byte(url.QueryEscape(originalNode.Value))) _, err := writer.Write([]byte(url.QueryEscape(originalNode.Value)))

View File

@ -8,8 +8,6 @@ import (
"io" "io"
"regexp" "regexp"
"strings" "strings"
yaml "gopkg.in/yaml.v3"
) )
type xmlEncoder struct { type xmlEncoder struct {
@ -41,14 +39,14 @@ func (e *xmlEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil return nil
} }
func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error { func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
encoder := xml.NewEncoder(writer) encoder := xml.NewEncoder(writer)
// hack so we can manually add newlines to procInst and directives // hack so we can manually add newlines to procInst and directives
e.writer = writer e.writer = writer
encoder.Indent("", e.indentString) encoder.Indent("", e.indentString)
var newLine xml.CharData = []byte("\n") var newLine xml.CharData = []byte("\n")
mapNode := unwrapDoc(node) mapNode := node.unwrapDocument()
if mapNode.Tag == "!!map" { if mapNode.Tag == "!!map" {
// make sure <?xml .. ?> processing instructions are encoded first // make sure <?xml .. ?> processing instructions are encoded first
for i := 0; i < len(mapNode.Content); i += 2 { for i := 0; i < len(mapNode.Content); i += 2 {
@ -82,18 +80,18 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
} }
switch node.Kind { switch node.Kind {
case yaml.MappingNode: case MappingNode:
err := e.encodeTopLevelMap(encoder, node) err := e.encodeTopLevelMap(encoder, node)
if err != nil { if err != nil {
return err return err
} }
case yaml.DocumentNode: case DocumentNode:
err := e.encodeComment(encoder, headAndLineComment(node)) err := e.encodeComment(encoder, headAndLineComment(node))
if err != nil { if err != nil {
return err return err
} }
unwrappedNode := unwrapDoc(node) unwrappedNode := node.unwrapDocument()
if unwrappedNode.Kind != yaml.MappingNode { if unwrappedNode.Kind != MappingNode {
return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", unwrappedNode.Tag) return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", unwrappedNode.Tag)
} }
err = e.encodeTopLevelMap(encoder, unwrappedNode) err = e.encodeTopLevelMap(encoder, unwrappedNode)
@ -104,7 +102,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
if err != nil { if err != nil {
return err return err
} }
case yaml.ScalarNode: case ScalarNode:
var charData xml.CharData = []byte(node.Value) var charData xml.CharData = []byte(node.Value)
err := encoder.EncodeToken(charData) err := encoder.EncodeToken(charData)
if err != nil { if err != nil {
@ -119,7 +117,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
} }
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) error { func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode) error {
err := e.encodeComment(encoder, headAndLineComment(node)) err := e.encodeComment(encoder, headAndLineComment(node))
if err != nil { if err != nil {
return err return err
@ -178,7 +176,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) er
return e.encodeComment(encoder, footComment(node)) return e.encodeComment(encoder, footComment(node))
} }
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error { func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
err := encoder.EncodeToken(start) err := encoder.EncodeToken(start)
if err != nil { if err != nil {
return err return err
@ -186,7 +184,7 @@ func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xm
return e.encodeComment(encoder, headComment(node)) return e.encodeComment(encoder, headComment(node))
} }
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error { func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
err := encoder.EncodeToken(start.End()) err := encoder.EncodeToken(start.End())
if err != nil { if err != nil {
return err return err
@ -194,13 +192,13 @@ func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.
return e.encodeComment(encoder, footComment(node)) return e.encodeComment(encoder, footComment(node))
} }
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error { func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
switch node.Kind { switch node.Kind {
case yaml.MappingNode: case MappingNode:
return e.encodeMap(encoder, node, start) return e.encodeMap(encoder, node, start)
case yaml.SequenceNode: case SequenceNode:
return e.encodeArray(encoder, node, start) return e.encodeArray(encoder, node, start)
case yaml.ScalarNode: case ScalarNode:
err := e.encodeStart(encoder, node, start) err := e.encodeStart(encoder, node, start)
if err != nil { if err != nil {
return err return err
@ -258,7 +256,7 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
return nil return nil
} }
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error { func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil { if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
return err return err
@ -280,7 +278,7 @@ func (e *xmlEncoder) isAttribute(name string) bool {
!strings.HasPrefix(name, e.prefs.ProcInstPrefix) !strings.HasPrefix(name, e.prefs.ProcInstPrefix)
} }
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error { func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
log.Debug("its a map") log.Debug("its a map")
//first find all the attributes and put them on the start token //first find all the attributes and put them on the start token
@ -289,7 +287,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.
value := node.Content[i+1] value := node.Content[i+1]
if e.isAttribute(key.Value) { if e.isAttribute(key.Value) {
if value.Kind == yaml.ScalarNode { if value.Kind == ScalarNode {
attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1) attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1)
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value}) start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value})
} else { } else {

View File

@ -73,9 +73,9 @@ func (ye *yamlEncoder) PrintLeadingContent(writer io.Writer, content string) err
return nil return nil
} }
func (ye *yamlEncoder) Encode(writer io.Writer, node *yaml.Node) error { func (ye *yamlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.Kind == yaml.ScalarNode && ye.prefs.UnwrapScalar { if node.Kind == ScalarNode && ye.prefs.UnwrapScalar {
return writeString(writer, node.Value+"\n") return writeString(writer, node.Value+"\n")
} }

View File

@ -189,7 +189,7 @@ type Operation struct {
UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs
} }
func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool { func recurseNodeArrayEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if len(lhs.Content) != len(rhs.Content) { if len(lhs.Content) != len(rhs.Content) {
return false return false
} }
@ -283,17 +283,17 @@ func parseSnippet(value string) (*CandidateNode, error) {
return result, err return result, err
} }
func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool { func recursiveNodeEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if lhs.Kind != rhs.Kind { if lhs.Kind != rhs.Kind {
return false return false
} }
if lhs.Kind == yaml.ScalarNode { if lhs.Kind == ScalarNode {
//process custom tags of scalar nodes. //process custom tags of scalar nodes.
//dont worry about matching tags of maps or arrays. //dont worry about matching tags of maps or arrays.
lhsTag := guessTagFromCustomType(lhs) lhsTag := lhs.guessTagFromCustomType()
rhsTag := guessTagFromCustomType(rhs) rhsTag := rhs.guessTagFromCustomType()
if lhsTag != rhsTag { if lhsTag != rhsTag {
return false return false
@ -303,11 +303,11 @@ func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
if lhs.Tag == "!!null" { if lhs.Tag == "!!null" {
return true return true
} else if lhs.Kind == yaml.ScalarNode { } else if lhs.Kind == ScalarNode {
return lhs.Value == rhs.Value return lhs.Value == rhs.Value
} else if lhs.Kind == yaml.SequenceNode { } else if lhs.Kind == SequenceNode {
return recurseNodeArrayEqual(lhs, rhs) return recurseNodeArrayEqual(lhs, rhs)
} else if lhs.Kind == yaml.MappingNode { } else if lhs.Kind == MappingNode {
return recurseNodeObjectEqual(lhs, rhs) return recurseNodeObjectEqual(lhs, rhs)
} }
return false return false
@ -382,19 +382,19 @@ func parseInt(numberString string) (int, error) {
return int(parsed), err return int(parsed), err
} }
func headAndLineComment(node *yaml.Node) string { func headAndLineComment(node *CandidateNode) string {
return headComment(node) + lineComment(node) return headComment(node) + lineComment(node)
} }
func headComment(node *yaml.Node) string { func headComment(node *CandidateNode) string {
return strings.Replace(node.HeadComment, "#", "", 1) return strings.Replace(node.HeadComment, "#", "", 1)
} }
func lineComment(node *yaml.Node) string { func lineComment(node *CandidateNode) string {
return strings.Replace(node.LineComment, "#", "", 1) return strings.Replace(node.LineComment, "#", "", 1)
} }
func footComment(node *yaml.Node) string { func footComment(node *CandidateNode) string {
return strings.Replace(node.FootComment, "#", "", 1) return strings.Replace(node.FootComment, "#", "", 1)
} }

View File

@ -115,8 +115,9 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
comment = startCommentCharaterRegExp.ReplaceAllString(comment, "") comment = startCommentCharaterRegExp.ReplaceAllString(comment, "")
comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n") comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n")
node := &yaml.Node{Kind: yaml.ScalarNode, Value: comment, Tag: "!!str"} result := candidate.CreateReplacement()
result := candidate.CreateReplacement(node) result.Kind = ScalarNode
result.Tag = "!!str"
result.LeadingContent = "" // don't include the leading yaml content when retrieving a comment result.LeadingContent = "" // don't include the leading yaml content when retrieving a comment
results.PushBack(result) results.PushBack(result)
} }

View File

@ -3,8 +3,6 @@ package yqlib
import ( import (
"fmt" "fmt"
"strconv" "strconv"
yaml "gopkg.in/yaml.v3"
) )
type compareTypePref struct { type compareTypePref struct {
@ -32,27 +30,27 @@ func compare(prefs compareTypePref) func(d *dataTreeNavigator, context Context,
return createBooleanCandidate(lhs, false), nil return createBooleanCandidate(lhs, false), nil
} }
lhs.Node = unwrapDoc(lhs.Node) lhsU := lhs.unwrapDocument()
rhs.Node = unwrapDoc(rhs.Node) rhsU := rhs.unwrapDocument()
switch lhs.Node.Kind { switch lhsU.Kind {
case yaml.MappingNode: case MappingNode:
return nil, fmt.Errorf("maps not yet supported for comparison") return nil, fmt.Errorf("maps not yet supported for comparison")
case yaml.SequenceNode: case SequenceNode:
return nil, fmt.Errorf("arrays not yet supported for comparison") return nil, fmt.Errorf("arrays not yet supported for comparison")
default: default:
if rhs.Node.Kind != yaml.ScalarNode { if rhsU.Kind != ScalarNode {
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhs.Node.Tag) return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhsU.Tag, rhs.Path, lhsU.Tag)
} }
target := lhs.CreateReplacement(&yaml.Node{}) target := lhs.CreateReplacement()
boolV, err := compareScalars(context, prefs, lhs.Node, rhs.Node) boolV, err := compareScalars(context, prefs, lhsU, rhsU)
return createBooleanCandidate(target, boolV), err return createBooleanCandidate(target, boolV), err
} }
} }
} }
func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) { func compareDateTime(layout string, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
lhsTime, err := parseDateTime(layout, lhs.Value) lhsTime, err := parseDateTime(layout, lhs.Value)
if err != nil { if err != nil {
return false, err return false, err
@ -73,9 +71,9 @@ func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *
} }
func compareScalars(context Context, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) { func compareScalars(context Context, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
lhsTag := guessTagFromCustomType(lhs) lhsTag := lhs.guessTagFromCustomType()
rhsTag := guessTagFromCustomType(rhs) rhsTag := rhs.guessTagFromCustomType()
isDateTime := lhs.Tag == "!!timestamp" isDateTime := lhs.Tag == "!!timestamp"
// if the lhs is a string, it might be a timestamp in a custom format. // if the lhs is a string, it might be a timestamp in a custom format.