iSeries下SQL解析带xmlns命名空间的XML文件失败如何解决
问题描述
- 存储场景:iSeries IFS目录下存放了ISO 20022标准camt.054.001.04格式的XML报文,文件开头内容如下:
<?xml version="1.0" encoding="UTF-8"?> <Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04"> <BkToCstmrDbtCdtNtfctn> <GrpHdr> <MsgId>CAMT054_20220708_173908613_1OUMVN4N</MsgId> <CreDtTm>2022-07-08T17:39:08.613Z</CreDtTm> <MsgPgntn> <PgNb>1</PgNb> <LastPgInd>true</LastPgInd> </MsgPgntn> <AddtlInf>SPS/1.7/PROD</AddtlInf> </GrpHdr> <Ntfctn>
- 原有提取SQL执行后无法返回预期结果,语句如下:
SELECT XMLDOC.* FROM (VALUES(XMLPARSE(DOCUMENT GET_XML_FILE('/temp/CAMT054.xml')) )) AS XMLFILE(FATTURE), XMLTABLE('$doc/Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/NtryDtls/TxDtls' PASSING XMLFILE.FATTURE AS "doc" COLUMNS Reference VARCHAR(27) PATH 'RmtInf/Strd/CdtrRefInf/Ref', Amount DECIMAL(17, 2) PATH 'AmtDtls/TxAmt/Amt' ) AS XMLDOC
- 验证现象:手动删除
<Document>标签上的xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04"命名空间声明后,上述SQL可正常返回结果。需求为不修改源XML文件解决问题,已知数据库提供XMLNAMESPACES函数,需确认其是否可解决该问题。
问题原因
XPath默认匹配无命名空间的节点,当XML根节点声明了默认命名空间时,文档内所有未显式指定命名空间的子节点都归属于该默认命名空间,原SQL中的XPath路径没有声明对应命名空间,无法匹配到带命名空间的节点,因此返回空结果。
解决方案
XMLNAMESPACES函数完全可以解决该问题,不需要修改源XML文件,只需要在XMLTABLE函数中声明对应的命名空间即可。
写法1:声明为默认命名空间(推荐,无需修改原有XPath路径)
SELECT XMLDOC.* FROM (VALUES(XMLPARSE(DOCUMENT GET_XML_FILE('/temp/CAMT054.xml')) )) AS XMLFILE(FATTURE), XMLTABLE( -- 声明XML使用的默认命名空间 XMLNAMESPACES(DEFAULT 'urn:iso:std:iso:20022:tech:xsd:camt.054.001.04'), '$doc/Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/NtryDtls/TxDtls' PASSING XMLFILE.FATTURE AS "doc" COLUMNS Reference VARCHAR(27) PATH 'RmtInf/Strd/CdtrRefInf/Ref', Amount DECIMAL(17, 2) PATH 'AmtDtls/TxAmt/Amt' ) AS XMLDOC
写法2:自定义命名空间前缀
如果不想声明为默认命名空间,可以给命名空间自定义前缀,注意此时XPath路径中的所有节点都需要加上对应前缀:
SELECT XMLDOC.* FROM (VALUES(XMLPARSE(DOCUMENT GET_XML_FILE('/temp/CAMT054.xml')) )) AS XMLFILE(FATTURE), XMLTABLE( -- 自定义前缀camt绑定目标命名空间 XMLNAMESPACES('urn:iso:std:iso:20022:tech:xsd:camt.054.001.04' AS "camt"), '$doc/camt:Document/camt:BkToCstmrDbtCdtNtfctn/camt:Ntfctn/camt:Ntry/camt:NtryDtls/camt:TxDtls' PASSING XMLFILE.FATTURE AS "doc" COLUMNS Reference VARCHAR(27) PATH 'camt:RmtInf/camt:Strd/camt:CdtrRefInf/camt:Ref', Amount DECIMAL(17, 2) PATH 'camt:AmtDtls/camt:TxAmt/camt:Amt' ) AS XMLDOC
两种写法执行效果完全一致,优先选择第一种写法,改动量最小。
内容的提问来源于stack exchange,提问作者Nifriz
相关产品推荐
相关产品推荐

