是否可以使用jq/yq/xq从JSON或YAML转换为XML

问题描述 投票:0回答:2

我已成功使用

XML
YAML
 文件转换为 
xq

文件

是否可以使用以下工具

jq
yq
xq
YAML
JSON
转换回
XML
格式?

这是我的样本

JSON
文件的示例:

{
  "security-settings": {
    "@xmlns": "urn:activemq:core",
    "security-setting": {
      "@match": "#",
      "permission": [
        {
          "@type": "createNonDurableQueue",
          "@roles": "admins"
        },
        {
          "@type": "deleteNonDurableQueue",
          "@roles": "admins"
        },
        {
          "@type": "manage",
          "@roles": "admins"
        }
      ]
    }
  }
}

感谢您的任何帮助或建议。


附加信息:

我最初使用的源 XML 如下:

<?xml version="1.0"?>
<security-settings xmlns="urn:activemq:core">
  <security-setting match="#">
    <permission type="createNonDurableQueue" roles="admins"/>
    <permission type="deleteNonDurableQueue" roles="admins"/>
    <permission type="createDurableQueue" roles="admins"/>
    <permission type="deleteDurableQueue" roles="admins"/>
    <permission type="createAddress" roles="admins"/>
    <permission type="deleteAddress" roles="admins"/>
    <permission type="consume" roles="admins"/>
    <permission type="browse" roles="admins"/>
    <permission type="send" roles="admins"/>
    <permission type="manage" roles="admins"/>
  </security-setting>
</security-settings>

使用命令

XML
JSON
xq -yY < security-settings.xml
的前向转换生成了
JSON
输出:

{
  "security-settings": {
    "@xmlns": "urn:activemq:core",
    "security-setting": {
      "@match": "#",
      "permission": [
        {
          "@type": "createNonDurableQueue",
          "@roles": "admins"
        },
        {
          "@type": "deleteNonDurableQueue",
          "@roles": "admins"
        },
        {
          "@type": "createDurableQueue",
          "@roles": "admins"
        },
        {
          "@type": "deleteDurableQueue",
          "@roles": "admins"
        },
        {
          "@type": "createAddress",
          "@roles": "admins"
        },
        {
          "@type": "deleteAddress",
          "@roles": "admins"
        },
        {
          "@type": "consume",
          "@roles": "admins"
        },
        {
          "@type": "browse",
          "@roles": "admins"
        },
        {
          "@type": "send",
          "@roles": "admins"
        },
        {
          "@type": "manage",
          "@roles": "admins"
        }
      ]
    }
  }
}

通过运行

yq -o=xml -P json_file
进行从
JSON
XML
的向后转换建议的本机转换不会生成与源
XML
相同的结果,如前面所示。

<security-settings>
  <@xmlns>urn:activemq:core</@xmlns>
  <security-setting>
    <@match>#</@match>
    <permission>
      <@type>createNonDurableQueue</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>deleteNonDurableQueue</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>createDurableQueue</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>deleteDurableQueue</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>createAddress</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>deleteAddress</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>consume</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>browse</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>send</@type>
      <@roles>admins</@roles>
    </permission>
    <permission>
      <@type>manage</@type>
      <@roles>admins</@roles>
    </permission>
  </security-setting>
</security-settings>

我在 Fedora 36 虚拟机上运行,这是我在盒子上安装的 yq

yq --version
yq 3.0.2

yq --help
usage: yq [options] <jq filter> [input file...]

yq: Command-line YAML processor - jq wrapper for YAML documents

yq transcodes YAML documents to JSON and passes them to jq.
See https://github.com/kislyuk/yq for more information.

positional arguments:
  jq_filter
  files

options:
  -h, --help            show this help message and exit
  --yaml-output, --yml-output, -y
                        Transcode jq JSON output back into YAML and emit it
  --yaml-roundtrip, --yml-roundtrip, -Y
                        Transcode jq JSON output back into YAML and emit it. Preserve YAML tags and styles by representing them as extra items in their enclosing mappings and sequences while in JSON. This option is incompatible with jq filters that do not expect these extra items.
  --width WIDTH, -w WIDTH
                        When using --yaml-output, specify string wrap width
  --indentless-lists, --indentless
                        When using --yaml-output, indent block style lists (sequences) with 0 spaces instead of 2
  --in-place, -i        Edit files in place (no backup - use caution)
  --version             show program's version number and exit

jq - commandline JSON processor [version 1.6]

Usage:  jq [options] <jq filter> [file...]
    jq [options] --args <jq filter> [strings...]
    jq [options] --jsonargs <jq filter> [JSON_TEXTS...]

jq is a tool for processing JSON inputs, applying the given filter to
its JSON text inputs and producing the filter's results as JSON on
standard output.

The simplest filter is ., which copies jq's input to its output
unmodified (except for formatting, but note that IEEE754 is used
for number representation internally, with all that that implies).

For more advanced filters see the jq(1) manpage ("man jq")
and/or https://stedolan.github.io/jq

Example:

    $ echo '{"foo": 0}' | jq .
    {
        "foo": 0
    }

Some of the options include:
  -c               compact instead of pretty-printed output;
  -n               use `null` as the single input value;
  -e               set the exit status code based on the output;
  -s               read (slurp) all inputs into an array; apply filter to it;
  -r               output raw strings, not JSON texts;
  -R               read raw strings, not JSON texts;
  -C               colorize JSON;
  -M               monochrome (don't colorize JSON);
  -S               sort keys of objects on output;
  --tab            use tabs for indentation;
  --arg a v        set variable $a to value <v>;
  --argjson a v    set variable $a to JSON value <v>;
  --slurpfile a f  set variable $a to an array of JSON texts read from <f>;
  --rawfile a f    set variable $a to a string consisting of the contents of <f>;
  --args           remaining arguments are string arguments, not files;
  --jsonargs       remaining arguments are JSON arguments, not files;
  --               terminates argument processing;

Named arguments are also available as $ARGS.named[], while
positional arguments are available as $ARGS.positional[].

See the manpage for more options.

@池上

这是输出:

回显ele_value | xq

{
  "ele": {
    "@attr_name": "attr_value",
    "#text": "ele_value"
  }
}

回显ele_value | xq | ./yq_linux_amd64 -o=xml -P

<ele>
  <@attr_name>attr_value</@attr_name>
  <#text>ele_value</#text>
</ele>
json xml jq yq xq
2个回答
6
投票

jq:

"@"     as $attr_prefix |
"#text" as $content_key |

# ">" (only) needs to be escaped if preceded by "]]". We'll do it unconditionally.
# Some whitespace also needs escaping, at least in attribute. Not done here.
{ "&": "&amp;", "<": "&lt;", ">": "&gt;"    } as $escapes      |
{ "&": "&amp;", "<": "&lt;", "\"": "&quot;" } as $attr_escapes |

def text_to_xml:          split( "" ) | map( $escapes[.]      // . ) | join( "" );
def text_to_xml_attr_val: split( "" ) | map( $attr_escapes[.] // . ) | join( "" );

def node_to_xml:
   if type == "string" then
      text_to_xml
   else
      (
         if .attrs then
            .attrs |
            to_entries |
            map( " " + .key + "=\"" + ( .value | text_to_xml_attr_val ) + "\"" ) |
            join( "" )
         else
            ""
         end
      ) as $attrs |

      if .children and ( .children | length ) > 0 then
         ( .children | map( node_to_xml ) | join( "" ) ) as $children |
         "<" + .name + $attrs + ">" + $children + "</" + .name + ">"
      else
         "<" + .name + $attrs + "/>"
      end
   end
;

def fix_tree( $name ):
   type as $type |
   if $type == "array" then
      .[] | fix_tree( $name )
   elif $type == "object" then
      reduce to_entries[] as { key: $k, value: $v } (
         { name: $name, attrs: {}, children: [] };

         if $k[0:1] == $attr_prefix then
            .attrs[ $k[1:] ] = $v
         elif $k == $content_key then
            .children += [ $v ]
         else
            .children += [ $v | fix_tree( $k ) ]
         end
      )
   else
      { name: $name, attrs: {}, children: [ . ] }
   end
;

def fix_tree: fix_tree( "" ) | .children[];

fix_tree | node_to_xml
jqplay 上

演示


它是使用

调用的
jq -r 'above progam' file.json >file.xml

您还可以将程序放入文件中(例如

json_to_xml.jq
)并使用以下命令:

jq -rf json_to_xml.jq file.json >file.xml

我采取了两步走的方法。我首先将输入转换为明确的格式,然后将此结果转换为 XML。这两个步骤可以合并。这是所提供输入的第一次转换的结果:

{
  "name": "security-settings",
  "attrs": {
    "xmlns": "urn:activemq:core"
  },
  "children": [
    {
      "name": "security-setting",
      "attrs": {
        "match": "#"
      },
      "children": [
        {
          "name": "permission",
          "attrs": {
            "type": "createNonDurableQueue",
            "roles": "admins"
          },
          "children": []
        },
        {
          "name": "permission",
          "attrs": {
            "type": "deleteNonDurableQueue",
            "roles": "admins"
          },
          "children": []
        },
        {
          "name": "permission",
          "attrs": {
            "type": "manage",
            "roles": "admins"
          },
          "children": []
        }
      ]
    }
  ]
}

请注意,原始 XML 转换后的格式是有损的。例如,它会丢失具有不同名称的 XML 元素的相对顺序。这意味着上述程序的输出可能与原始 XML 有很大不同。但除非您使用无损的 JSON 模式,否则这是不可避免的。


5
投票

另一种工具,也称为

yq
,使用类似
jq
的语法,并支持 XML 和 JSON 之间的转换。您可以从发布页面下载最新版本。

与 kislyuk 的

yq/xq
不同,它不使用
jq
进行处理,因此您可能需要稍微调整
jq
脚本,但 mikefarah 的
yq
确实支持 XML 和 JSON 之间的转换。

有了这个 yq,就可以使用以下命令重新生成 XML:

./yq_linux_amd64               \
    --xml-attribute-prefix @   \
    --xml-content-name '#text' \
    --input-format yaml        \
    --output-format xml        \
    security-settings.yaml

同样的命令也适用于 JSON 输入,因为 JSON 是 YAML 的子集。

© www.soinside.com 2019 - 2024. All rights reserved.