考虑以下存储在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有什么问题?
答案 0 :(得分:2)
由于两个问题,您的第二个xpath()不返回任何内容。首先:您需要使用//tCatSnVsn_Pmax
,因为xml_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