xml - 如何在 Postgres 中将 XML 转换为 JSONB

标签 xml postgresql jsonb

我有一个表,Table1,其中包含一个 XML data type列、ColumnA 和另一个 JSONB 列 ColumnB

如何将数据从 ColumnA 转换为 ColumnB,可能使用 SQL UPDATE 语句。 Postgres 中是否有执行此操作的内置函数?

最佳答案

据我所知,没有开箱即用的功能。

尝试:

create or replace function xml_to_json(p_xml xml) returns jsonb as $$
declare
  result json;
  root text;
  childs jsonb;
  attr jsonb;
  txt text;
begin
  -- Get root element name
  select (xpath('name(/*)', p_xml))[1]::text into root;

  -- Process child nodes
  select json_agg(xml_to_json(z))
  from unnest(xpath('/'||root||'/*', p_xml)) with ordinality as c(z,i)
  into childs;

  -- Read attributes
  select jsonb_agg(jsonb_build_object((xpath('name(/'||root||'/@*['||i||'])', p_xml))[1]::text, v))
  from unnest(xpath('/'||root||'/@*', p_xml)::text[]) with ordinality as a(v,i) 
  into attr;

  -- Read text
  select (xpath('/'||root||'/text()', p_xml))[1]::text into txt;

  -- Build object
  result := jsonb_build_object(root, jsonb_build_object('attr', attr, 'text', txt, 'childs', childs));
  return result;
end $$ language plpgsql immutable;

测试:

with t(x) as (values
('<root bar="foo" name="test" foo="bar">
  <aaa bbb="111">
    foo
    bar
  </aaa>
  <bbb>
    <ccc>222</ccc>
  </bbb>
</root>'::xml),
('<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book>
    <title lang="en">Harry Potter</title>
    <price>29.99</price>
  </book>
  <book>
    <title lang="en">Learning XML</title>
    <price>39.95</price>
  </book>
</bookstore>'))
select jsonb_pretty(xml_to_json(x)) from t;

并输出:

                      jsonb_pretty                       
---------------------------------------------------------
 {                                                      +
     "root": {                                          +
         "attr": [                                      +
             {                                          +
                 "bar": "foo"                           +
             },                                         +
             {                                          +
                 "name": "test"                         +
             },                                         +
             {                                          +
                 "foo": "bar"                           +
             }                                          +
         ],                                             +
         "text": "\n  ",                                +
         "childs": [                                    +
             {                                          +
                 "aaa": {                               +
                     "attr": [                          +
                         {                              +
                             "bbb": "111"               +
                         }                              +
                     ],                                 +
                     "text": "\n    foo\n    bar\n  ",  +
                     "childs": null                     +
                 }                                      +
             },                                         +
             {                                          +
                 "bbb": {                               +
                     "attr": null,                      +
                     "text": "\n    ",                  +
                     "childs": [                        +
                         {                              +
                             "ccc": {                   +
                                 "attr": null,          +
                                 "text": "222",         +
                                 "childs": null         +
                             }                          +
                         }                              +
                     ]                                  +
                 }                                      +
             }                                          +
         ]                                              +
     }                                                  +
 }
 {                                                      +
     "bookstore": {                                     +
         "attr": null,                                  +
         "text": "\n  ",                                +
         "childs": [                                    +
             {                                          +
                 "book": {                              +
                     "attr": null,                      +
                     "text": "\n    ",                  +
                     "childs": [                        +
                         {                              +
                             "title": {                 +
                                 "attr": [              +
                                     {                  +
                                         "lang": "en"   +
                                     }                  +
                                 ],                     +
                                 "text": "Harry Potter",+
                                 "childs": null         +
                             }                          +
                         },                             +
                         {                              +
                             "price": {                 +
                                 "attr": null,          +
                                 "text": "29.99",       +
                                 "childs": null         +
                             }                          +
                         }                              +
                     ]                                  +
                 }                                      +
             },                                         +
             {                                          +
                 "book": {                              +
                     "attr": null,                      +
                     "text": "\n    ",                  +
                     "childs": [                        +
                         {                              +
                             "title": {                 +
                                 "attr": [              +
                                     {                  +
                                         "lang": "en"   +
                                     }                  +
                                 ],                     +
                                 "text": "Learning XML",+
                                 "childs": null         +
                             }                          +
                         },                             +
                         {                              +
                             "price": {                 +
                                 "attr": null,          +
                                 "text": "39.95",       +
                                 "childs": null         +
                             }                          +
                         }                              +
                     ]                                  +
                 }                                      +
             }                                          +
         ]                                              +
     }                                                  +
 }
(2 rows)

关于xml - 如何在 Postgres 中将 XML 转换为 JSONB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38142623/

相关文章:

postgresql - 使用 MyBatis 将 PostgreSQL 聚合返回到 HashMap

sql - 选择与 PostgreSQL 条件匹配的最新连续记录

postgresql - 如何从每个元素 json 数组 postgres 中删除字段?

postgresql - 在 ILIKE postgres 查询上创建 GIN 索引

ruby-on-rails - Rails 5 在 jsonb 嵌套数组中搜索其他 2 个日期之间的日期

android - 将布局包裹在边框中

php - 将特定字符串从 xml 导出到 mysql 表

java - 在Android中,如何将数据从类传递到相应的布局/fragment 文件?

php - Magento 在静态 block 中调用子 html

swift - 如何帮助 Vapor 成功地与我的 PostgreSQL 服务器进行 SSL 握手?