添加xmlns属性后PostgreSQL XML查询无结果,如何修改?
解决PostgreSQL XPath查询XML命名空间问题
当XML根节点添加默认命名空间xmlns="http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2"后,所有未指定前缀的元素都会归属到这个命名空间下。而你原来的XPath查询是针对无命名空间的元素,自然匹配不到任何结果,返回0条记录。
下面提供两种可行的修改方案:
方案1:使用命名空间映射(推荐)
PostgreSQL的xpath函数支持第三个参数,用于指定命名空间与前缀的映射关系。给目标命名空间绑定一个前缀,然后在XPath路径中给所有元素添加该前缀即可:
SELECT (xpath('//ns:TypeCode/text()', myTempTable.myXmlColumn, ARRAY[ARRAY['ns', 'http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2']]))[1]::text AS c1 ,(xpath('//ns:TypeName/text()', myTempTable.myXmlColumn, ARRAY[ARRAY['ns', 'http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2']]))[1]::text AS c2 ,(xpath('//ns:BookDate/text()', myTempTable.myXmlColumn, ARRAY[ARRAY['ns', 'http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2']]))[1]::text AS c3 ,(xpath('//ns:BankRef/text()', myTempTable.myXmlColumn, ARRAY[ARRAY['ns', 'http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2']]))[1]::text AS c4 ,(xpath('//ns:AccAmt/text()', myTempTable.myXmlColumn, ARRAY[ARRAY['ns', 'http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2']]))[1]::text AS c5 ,myTempTable.myXmlColumn as myXmlElement FROM unnest( xpath( '/ns:FIDAVISTA/ns:Statement/ns:AccountSet/ns:CcyStmt/ns:TrxSet', XMLPARSE(document (SELECT xml_data FROM bank_xml WHERE id = 1)), ARRAY[ARRAY['ns', 'http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2']] ) ) AS myTempTable(myXmlColumn) ;
方案2:忽略命名空间匹配
通过local-name()函数匹配元素的本地名称,不管元素所属的命名空间,写法更简单:
SELECT (xpath('//*[local-name()="TypeCode"]/text()', myTempTable.myXmlColumn))[1]::text AS c1 ,(xpath('//*[local-name()="TypeName"]/text()', myTempTable.myXmlColumn))[1]::text AS c2 ,(xpath('//*[local-name()="BookDate"]/text()', myTempTable.myXmlColumn))[1]::text AS c3 ,(xpath('//*[local-name()="BankRef"]/text()', myTempTable.myXmlColumn))[1]::text AS c4 ,(xpath('//*[local-name()="AccAmt"]/text()', myTempTable.myXmlColumn))[1]::text AS c5 ,myTempTable.myXmlColumn as myXmlElement FROM unnest( xpath( '/*[local-name()="FIDAVISTA"]/*[local-name()="Statement"]/*[local-name()="AccountSet"]/*[local-name()="CcyStmt"]/*[local-name()="TrxSet"]', XMLPARSE(document (SELECT xml_data FROM bank_xml WHERE id = 1)) ) ) AS myTempTable(myXmlColumn) ;
方案对比
- 方案1:符合XML命名空间规范,能避免不同命名空间下同名元素的误匹配,适合复杂XML场景,推荐优先使用。
- 方案2:写法简洁,但如果XML中存在不同命名空间的同名元素,可能会匹配到非目标元素,仅适合结构简单、无同名元素的XML场景。
内容的提问来源于stack exchange,提问作者Janis T
相关产品推荐
相关产品推荐

