diff --git a/cmd/root.go b/cmd/root.go index df740104..058dfd7d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -54,7 +54,7 @@ yq -P sample.json yqlib.InitExpressionParser() if (inputFormat == "x" || inputFormat == "xml") && outputFormat != "x" && outputFormat != "xml" && - yqlib.XMLPreferences.AttributePrefix == "+" { + yqlib.ConfiguredXMLPreferences.AttributePrefix == "+" { yqlib.GetLogger().Warning("The default xml-attribute-prefix will change in the v4.30 to `+@` to avoid " + "naming conflicts with the default content name, directive name and proc inst prefix. If you need to keep " + "`+` please set that value explicityly with --xml-attribute-prefix.") @@ -73,15 +73,15 @@ yq -P sample.json rootCmd.PersistentFlags().StringVarP(&outputFormat, "output-format", "o", "yaml", "[yaml|y|json|j|props|p|xml|x] output format type.") rootCmd.PersistentFlags().StringVarP(&inputFormat, "input-format", "p", "yaml", "[yaml|y|props|p|xml|x] parse format for input. Note that json is a subset of yaml.") - rootCmd.PersistentFlags().StringVar(&yqlib.XMLPreferences.AttributePrefix, "xml-attribute-prefix", "+", "prefix for xml attributes") - rootCmd.PersistentFlags().StringVar(&yqlib.XMLPreferences.ContentName, "xml-content-name", "+content", "name for xml content (if no attribute name is present).") - rootCmd.PersistentFlags().BoolVar(&yqlib.XMLPreferences.StrictMode, "xml-strict-mode", false, "enables strict parsing of XML. See https://pkg.go.dev/encoding/xml for more details.") - rootCmd.PersistentFlags().BoolVar(&yqlib.XMLPreferences.KeepNamespace, "xml-keep-namespace", true, "enables keeping namespace after parsing attributes") - rootCmd.PersistentFlags().BoolVar(&yqlib.XMLPreferences.UseRawToken, "xml-raw-token", true, "enables using RawToken method instead Token. Commonly disables namespace translations. See https://pkg.go.dev/encoding/xml#Decoder.RawToken for details.") - rootCmd.PersistentFlags().StringVar(&yqlib.XMLPreferences.ProcInstPrefix, "xml-proc-inst-prefix", "+p_", "prefix for xml processing instructions (e.g. )") - rootCmd.PersistentFlags().StringVar(&yqlib.XMLPreferences.DirectiveName, "xml-directive-name", "+directive", "name for xml directives (e.g. )") - rootCmd.PersistentFlags().BoolVar(&yqlib.XMLPreferences.SkipProcInst, "xml-skip-proc-inst", false, "skip over process instructions (e.g. )") - rootCmd.PersistentFlags().BoolVar(&yqlib.XMLPreferences.SkipDirectives, "xml-skip-directives", false, "skip over directives (e.g. )") + rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.AttributePrefix, "xml-attribute-prefix", "+", "prefix for xml attributes") + rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.ContentName, "xml-content-name", "+content", "name for xml content (if no attribute name is present).") + rootCmd.PersistentFlags().BoolVar(&yqlib.ConfiguredXMLPreferences.StrictMode, "xml-strict-mode", false, "enables strict parsing of XML. See https://pkg.go.dev/encoding/xml for more details.") + rootCmd.PersistentFlags().BoolVar(&yqlib.ConfiguredXMLPreferences.KeepNamespace, "xml-keep-namespace", true, "enables keeping namespace after parsing attributes") + rootCmd.PersistentFlags().BoolVar(&yqlib.ConfiguredXMLPreferences.UseRawToken, "xml-raw-token", true, "enables using RawToken method instead Token. Commonly disables namespace translations. See https://pkg.go.dev/encoding/xml#Decoder.RawToken for details.") + rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.ProcInstPrefix, "xml-proc-inst-prefix", "+p_", "prefix for xml processing instructions (e.g. )") + rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.DirectiveName, "xml-directive-name", "+directive", "name for xml directives (e.g. )") + rootCmd.PersistentFlags().BoolVar(&yqlib.ConfiguredXMLPreferences.SkipProcInst, "xml-skip-proc-inst", false, "skip over process instructions (e.g. )") + rootCmd.PersistentFlags().BoolVar(&yqlib.ConfiguredXMLPreferences.SkipDirectives, "xml-skip-directives", false, "skip over directives (e.g. )") rootCmd.PersistentFlags().BoolVarP(&nullInput, "null-input", "n", false, "Don't read input, simply evaluate the expression given. Useful for creating docs from scratch.") rootCmd.PersistentFlags().BoolVarP(&noDocSeparators, "no-doc", "N", false, "Don't print document separators (---)") diff --git a/cmd/utils.go b/cmd/utils.go index b201b1db..007ada69 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -63,7 +63,7 @@ func configureDecoder() (yqlib.Decoder, error) { } switch yqlibInputFormat { case yqlib.XMLInputFormat: - return yqlib.NewXMLDecoder(yqlib.XMLPreferences), nil + return yqlib.NewXMLDecoder(yqlib.ConfiguredXMLPreferences), nil case yqlib.PropertiesInputFormat: return yqlib.NewPropertiesDecoder(), nil case yqlib.JsonInputFormat: @@ -107,7 +107,7 @@ func configureEncoder(format yqlib.PrinterOutputFormat) yqlib.Encoder { case yqlib.YamlOutputFormat: return yqlib.NewYamlEncoder(indent, colorsEnabled, !noDocSeparators, unwrapScalar) case yqlib.XMLOutputFormat: - return yqlib.NewXMLEncoder(indent, yqlib.XMLPreferences) + return yqlib.NewXMLEncoder(indent, yqlib.ConfiguredXMLPreferences) } panic("invalid encoder") } diff --git a/pkg/yqlib/decoder_xml.go b/pkg/yqlib/decoder_xml.go index d74c579a..8a7e79f0 100644 --- a/pkg/yqlib/decoder_xml.go +++ b/pkg/yqlib/decoder_xml.go @@ -15,10 +15,10 @@ type xmlDecoder struct { reader io.Reader readAnything bool finished bool - prefs xmlPreferences + prefs XmlPreferences } -func NewXMLDecoder(prefs xmlPreferences) Decoder { +func NewXMLDecoder(prefs XmlPreferences) Decoder { return &xmlDecoder{ finished: false, prefs: prefs, diff --git a/pkg/yqlib/encoder_xml.go b/pkg/yqlib/encoder_xml.go index 012e64b7..5d76194d 100644 --- a/pkg/yqlib/encoder_xml.go +++ b/pkg/yqlib/encoder_xml.go @@ -12,10 +12,10 @@ import ( type xmlEncoder struct { indentString string writer io.Writer - prefs xmlPreferences + prefs XmlPreferences } -func NewXMLEncoder(indent int, prefs xmlPreferences) Encoder { +func NewXMLEncoder(indent int, prefs XmlPreferences) Encoder { var indentString = "" for index := 0; index < indent; index++ { diff --git a/pkg/yqlib/lexer_participle.go b/pkg/yqlib/lexer_participle.go index 6cc745cc..66715f3a 100644 --- a/pkg/yqlib/lexer_participle.go +++ b/pkg/yqlib/lexer_participle.go @@ -76,7 +76,7 @@ var participleYqRules = []*participleYqRule{ {"Base64d", `@base64d`, decodeOp(Base64InputFormat), 0}, {"Base64", `@base64`, encodeWithIndent(Base64OutputFormat, 0), 0}, - {"LoadXML", `load_?xml|xml_?load`, loadOp(NewXMLDecoder(XMLPreferences), false), 0}, + {"LoadXML", `load_?xml|xml_?load`, loadOp(NewXMLDecoder(ConfiguredXMLPreferences), false), 0}, {"LoadBase64", `load_?base64`, loadOp(NewBase64Decoder(), false), 0}, diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 910ab801..5494d72c 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -21,34 +21,6 @@ func InitExpressionParser() { } } -type xmlPreferences struct { - AttributePrefix string - ContentName string - StrictMode bool - KeepNamespace bool - UseRawToken bool - ProcInstPrefix string - DirectiveName string - SkipProcInst bool - SkipDirectives bool -} - -func NewDefaultXmlPreferences() xmlPreferences { - return xmlPreferences{ - AttributePrefix: "+", - ContentName: "+content", - StrictMode: false, - KeepNamespace: true, - UseRawToken: false, - ProcInstPrefix: "+p_", - DirectiveName: "+directive", - SkipProcInst: false, - SkipDirectives: false, - } -} - -var XMLPreferences = NewDefaultXmlPreferences() - var log = logging.MustGetLogger("yq-lib") var PrettyPrintExp = `(... | (select(tag != "!!str"), select(tag == "!!str") | select(test("(?i)^(y|yes|n|no|on|off)$") | not)) ) style=""` diff --git a/pkg/yqlib/operator_encoder_decoder.go b/pkg/yqlib/operator_encoder_decoder.go index e8b8a963..7a1c6a56 100644 --- a/pkg/yqlib/operator_encoder_decoder.go +++ b/pkg/yqlib/operator_encoder_decoder.go @@ -23,7 +23,7 @@ func configureEncoder(format PrinterOutputFormat, indent int) Encoder { case YamlOutputFormat: return NewYamlEncoder(indent, false, true, true) case XMLOutputFormat: - return NewXMLEncoder(indent, XMLPreferences) + return NewXMLEncoder(indent, ConfiguredXMLPreferences) case Base64OutputFormat: return NewBase64Encoder() } @@ -104,7 +104,7 @@ func decodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre case YamlInputFormat: decoder = NewYamlDecoder() case XMLInputFormat: - decoder = NewXMLDecoder(XMLPreferences) + decoder = NewXMLDecoder(ConfiguredXMLPreferences) case Base64InputFormat: decoder = NewBase64Decoder() case PropertiesInputFormat: diff --git a/pkg/yqlib/xml.go b/pkg/yqlib/xml.go new file mode 100644 index 00000000..7903c207 --- /dev/null +++ b/pkg/yqlib/xml.go @@ -0,0 +1,29 @@ +package yqlib + +type XmlPreferences struct { + AttributePrefix string + ContentName string + StrictMode bool + KeepNamespace bool + UseRawToken bool + ProcInstPrefix string + DirectiveName string + SkipProcInst bool + SkipDirectives bool +} + +func NewDefaultXmlPreferences() XmlPreferences { + return XmlPreferences{ + AttributePrefix: "+", + ContentName: "+content", + StrictMode: false, + KeepNamespace: true, + UseRawToken: false, + ProcInstPrefix: "+p_", + DirectiveName: "+directive", + SkipProcInst: false, + SkipDirectives: false, + } +} + +var ConfiguredXMLPreferences = NewDefaultXmlPreferences() diff --git a/pkg/yqlib/xml_test.go b/pkg/yqlib/xml_test.go index af78d76e..9963c947 100644 --- a/pkg/yqlib/xml_test.go +++ b/pkg/yqlib/xml_test.go @@ -414,11 +414,11 @@ var xmlScenarios = []formatScenario{ func testXMLScenario(t *testing.T, s formatScenario) { switch s.scenarioType { case "", "decode": - test.AssertResultWithContext(t, s.expected, processFormatScenario(s, NewXMLDecoder(XMLPreferences), NewYamlEncoder(4, false, true, true)), s.description) + test.AssertResultWithContext(t, s.expected, processFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewYamlEncoder(4, false, true, true)), s.description) case "encode": - test.AssertResultWithContext(t, s.expected, processFormatScenario(s, NewYamlDecoder(), NewXMLEncoder(2, XMLPreferences)), s.description) + test.AssertResultWithContext(t, s.expected, processFormatScenario(s, NewYamlDecoder(), NewXMLEncoder(2, ConfiguredXMLPreferences)), s.description) case "roundtrip": - test.AssertResultWithContext(t, s.expected, processFormatScenario(s, NewXMLDecoder(XMLPreferences), NewXMLEncoder(2, XMLPreferences)), s.description) + test.AssertResultWithContext(t, s.expected, processFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewXMLEncoder(2, ConfiguredXMLPreferences)), s.description) case "decode-keep-ns": prefs := NewDefaultXmlPreferences() prefs.KeepNamespace = true @@ -480,7 +480,7 @@ func documentXMLDecodeScenario(w *bufio.Writer, s formatScenario) { writeOrPanic(w, fmt.Sprintf("```bash\nyq -p=xml '%v' sample.xml\n```\n", expression)) writeOrPanic(w, "will output\n") - writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", processFormatScenario(s, NewXMLDecoder(XMLPreferences), NewYamlEncoder(2, false, true, true)))) + writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", processFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewYamlEncoder(2, false, true, true)))) } func documentXMLDecodeKeepNsScenario(w *bufio.Writer, s formatScenario) { @@ -549,7 +549,7 @@ func documentXMLEncodeScenario(w *bufio.Writer, s formatScenario) { writeOrPanic(w, "```bash\nyq -o=xml '.' sample.yml\n```\n") writeOrPanic(w, "will output\n") - writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processFormatScenario(s, NewYamlDecoder(), NewXMLEncoder(2, XMLPreferences)))) + writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processFormatScenario(s, NewYamlDecoder(), NewXMLEncoder(2, ConfiguredXMLPreferences)))) } func documentXMLRoundTripScenario(w *bufio.Writer, s formatScenario) { @@ -567,7 +567,7 @@ func documentXMLRoundTripScenario(w *bufio.Writer, s formatScenario) { writeOrPanic(w, "```bash\nyq -p=xml -o=xml '.' sample.xml\n```\n") writeOrPanic(w, "will output\n") - writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processFormatScenario(s, NewXMLDecoder(XMLPreferences), NewXMLEncoder(2, XMLPreferences)))) + writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewXMLEncoder(2, ConfiguredXMLPreferences)))) } func documentXMLSkipDirectrivesScenario(w *bufio.Writer, s formatScenario) {