【问题标题】:Extracting value of xml tag in PostgreSQL在PostgreSQL中提取xml标签的值
【发布时间】:2013-04-08 01:26:15
【问题描述】:

下面是我的 Postgres 表中的列响应。我想从我的 Postgres 数据库中的所有行中提取状态。状态可能是不同大小的,例如SUCCESS,所以我不想使用 substring 函数。有办法吗?

<?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status><responseType>COUNTRY_MISSING</responseType><country_info>USA</country_info><phone_country_code>1234</phone_country_code></response>

所以我的表结构是这样的

   Column    |            Type             |                        Modifiers                         

-------------+-----------------------------+----------------------------------------------------------

 id          | bigint                      | not null default nextval('events_id_seq'::regclass)
 hostname    | text                        | not null
 time        | timestamp without time zone | not null
 trn_type    | text                        | 
 db_ret_code | text                        | 
 request     | text                        | 
 response    | text                        | 
 wait_time   | text                        | 

我想从每个请求中提取状态。我该怎么做?

下面是示例行。并假设表名 abc_events

id          | 1870667
hostname    | abcd.local
time        | 2013-04-16 00:00:23.861
trn_type    | A
request     | <?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status><responseType>COUNTRY_MISSING</responseType><country_info>USA</country_info><phone_country_code>1234</phone_country_code></response>
response    | <?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status><responseType>COUNTRY_MISSING</responseType><country_info>USA</country_info><phone_country_code>1234</phone_country_code></response>

【问题讨论】:

  • request 有 xml 请求,response 有 xml 响应。我上面显示的 xml 是响应的一个示例。本质上,我试图从每个 xml 响应行中提取状态标记。

标签: xml postgresql xpath casting xml-parsing


【解决方案1】:

使用xpath()函数:

WITH x(col) AS (SELECT '<?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status></response>'::xml)
SELECT xpath('./status/text()', col) AS status
FROM   x

/text() 去除周围的&lt;status&gt; 标签。
返回xml 的数组 - 在这种情况下只有一个元素:

status
xml[]
-------
{ERROR_MISSING_DATA}

应用于您的表

针对您的问题更新,这可以简单地是:

SELECT id, xpath('./status/text()', response::xml) AS status
FROM   tbl;

如果您确定每行只有一个状态标签,您可以简单地从数组中提取第一项:

SELECT id, (xpath('./status/text()', response::xml))[1] AS status
FROM   tbl;

如果可以有多个状态项:

SELECT id, unnest(xpath('./status/text()', response::xml)) AS status
FROM   tbl;

每个id 获取 1-n 行。

转换为xml

由于您将列定义为 text 类型(而不是 xml,您需要显式转换为 xml。函数 xpath() 需要第二个参数类型xml。无类型的字符串常量会自动强制转换为 xml,但 text不会。您需要​​显式转换。

这无需显式强制转换即可工作:

  SELECT xpath('./status/text()'
      ,'<?xml version="1.0" ?><response><status>SUCCESS</status></response>')

CTE 就像我的第一个示例中一样需要“公用表表达式”中的每一列都有一个类型。如果我没有强制转换为特定类型,则会使用 unknown 类型 - not无类型字符串 相同。显然,unknownxml 之间没有实现直接转换。您必须先转换为textunknown_type_col::text::xml。最好马上投到::xml

这在 PostgreSQL 9.1 中得到了加强(我认为)。旧版本更宽松。

无论哪种方式,使用这些方法中的任何一种,字符串都必须是有效的xml,否则强制转换(隐式或显式)将引发异常。

【讨论】:

  • 您需要::xml 吗?我只是在做SELECT xpath('...', '&lt;raw&gt;xml&lt;/raw&gt;');,它似乎有效。
  • 我编辑了我的问题。基本上我想要的是从具有 xml 请求/响应的列中提取标签的值。
  • 我关注了它,但我收到此错误LINE 1: select unnest(xpath('./status/text()', request)) from abc_events ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. 它指向 xpath 函数。
  • @Phrogz:我添加了关于选角主题的一章,因为我最初的评论并不完全正确。在这种情况下,演员实际上是需要和 CTE ...
  • @ronak:我在回答中添加了一些内容。请注意有关转换为 xml 的附录。另请注意,我一开始的演员阵容错误。必须是::xml
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多