首页 > 解决方案 > PostgreSQL 绝对相对 xpath 位置

问题描述

考虑以下存储在 PostgreSQL 字段中的 xml 文档:

 <E_sProcedure xmlns="http://www.minushabens.com/2008/FMSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" modelCodeScheme="Emo_ex" modelCodeSchemeVersion="01" modelCodeValue="EMO_E_PROCEDURA" modelCodeMeaning="Section" sectionID="11">
        <tCatSnVsn_Pmax modelCodeScheme="Emodinamica_referto" modelCodeSchemeVersion="01" modelCodeValue="tCat4" modelCodeMeaning="My text"><![CDATA[1]]></tCatSnVsn_Pmax>
</E_sProcedure>

如果我运行以下查询,我会得到第 1 行的正确结果,而第 2 行什么也不返回:

SELECT
--Line 1
TRIM(BOTH FROM array_to_string((xpath('//child::*[@modelCodeValue="tCat4"]/text()', t.xml_element)),'')) as tCatSnVsn_Pmax_MEANING
--Line2
,TRIM(BOTH FROM array_to_string((xpath('/tCatSnVsn_Pmax/text()', t.xml_element)),'')) as tCatSnVsn_Pmax
FROM (
    SELECT unnest(xpath('//x:E_sProcedure', s.XMLDATA::xml, ARRAY[ARRAY['x', 'http://www.minushabens.com/2008/FMSchema']])) AS xml_element
    FROM sr_data as s)t;

第 2 行的 xpath 有什么问题?

标签: postgresqlxpath

解决方案


由于两个问题,您的第二个 xpath() 没有返回任何内容。首先:您需要使用//tCatSnVsn_Pmaxasxml_element仍然以<E_sProcedure>. 该路径/tCatSnVsn_Pmax尝试选择具有该名称的顶级元素。

但即便如此,由于命名空间,第二个也不会返回任何内容。你需要将相同的命名空间定义传递给 xpath(),所以你需要这样的东西:

SELECT (xpath('/x:tCatSnVsn_Pmax/text()', t.xml_element, ARRAY[ARRAY['x', 'http://www.minushabens.com/2008/FMSchema']]))[1] as tCatSnVsn_Pmax
FROM (
    SELECT unnest(xpath('//x:E_sProcedure', s.XMLDATA::xml, ARRAY[ARRAY['x', 'http://www.minushabens.com/2008/FMSchema']])) AS xml_element
    FROM sr_data as s
)t;

对于现代 Postgres 版本 (>= 10),我更喜欢将xmltable()其用于任何重要的事情。它使传递命名空间和访问多个属性或元素变得更加容易。

SELECT xt.*
FROM sr_data
  cross join 
      xmltable(xmlnamespaces ('http://www.minushabens.com/2008/FMSchema' as x),
               '/x:E_sProcedure'
               passing (xmldata::xml)
               columns 
                  sectionid text path '@sectionID', 
                  pmax text path 'x:tCatSnVsn_Pmax',
                  model_code_value text path 'x:tCatSnVsn_Pmax/@modelCodeValue') as xt

对于您的示例 XML,以上返回:

sectionid | pmax | model_code_value
----------+------+-----------------
11        | 1    | tCat4           

推荐阅读