如何用可选元素解析 xml
How to parse xml with optional elements
SEPA ISO XML 事务文件需要在 ASP:NET 4.6 MVC 控制器的 Postgres 9.1+ 中解析为平面 table。
我尝试了下面的代码,但这会产生错误的结果:
endaaa tasusumma orderinr
XX00221059842412 150.00 PV04131
XX00221059842412 0.38 PV04131
由于第二行没有 EndToEnd,所以第二行 orderinr 列中应该有空文本:
endaaa tasusumma orderinr
XX00221059842412 150.00 PV04131
XX00221059842412 0.38 null
如何解决这个问题?
可以通过其他方式进行解析e.q。使用 xslt 样式表进行转换或在客户端 ASP.NET 4.6 MVC 如果这更合理。
create temp table t(x xml, nsa text[][]) on commit drop;
insert into t values(
'<?xml version=''1.0'' encoding=''UTF-8''?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
<BkToCstmrStmt>
<Stmt>
<Acct>
<Id>
<IBAN>XX00221059842412</IBAN>
</Id>
</Acct>
<Ntry>
<Amt Ccy="EUR">150.00</Amt>
<NtryDtls>
<TxDtls>
<Refs>
<EndToEndId>PV04131</EndToEndId>
</Refs>
</TxDtls>
</NtryDtls>
</Ntry>
<Ntry>
<Amt Ccy="EUR">0.38</Amt>
<NtryDtls>
<TxDtls>
<Refs>
<AcctSvcrRef>2016080100178214-2</AcctSvcrRef>
</Refs>
</TxDtls>
</NtryDtls>
</Ntry>
</Stmt>
</BkToCstmrStmt>
</Document>
', ARRAY[ARRAY['ns','urn:iso:std:iso:20022:tech:xsd:camt.053.001.02']]);
SELECT
unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Acct/ns:Id/ns:IBAN/text()', x,nsa))::text AS endaaa,
unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Ntry/ns:Amt/text()', x,nsa))::text::numeric AS tasusumma
, unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Ntry/ns:NtryDtls/ns:TxDtls/ns:Refs/ns:EndToEndId/text()', x,nsa))::text AS orderinr
FROM t;
更新
使用 Hannes 的代码回答 returns Postgres 9.1 中的空行如何让它在 9.1 中工作?
也发布在 pgsql.general 邮件列表中。
您需要先提取所有 ns:Ntry 个元素,然后获取每个元素的数量和 EndToEndId:
SELECT
endaaa,
(xpath('ns:Amt/text()', x,nsa))[1]::text::numeric AS tasusumma,
(xpath('ns:NtryDtls/ns:TxDtls/ns:Refs/ns:EndToEndId/text()', x,nsa))[1] AS orderinr
FROM (
SELECT (xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Acct/ns:Id/ns:IBAN/text()', x,nsa))[1] as endaaa,
unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Ntry', x,nsa)) as x, nsa
FROM t
) Ntry
SEPA ISO XML 事务文件需要在 ASP:NET 4.6 MVC 控制器的 Postgres 9.1+ 中解析为平面 table。
我尝试了下面的代码,但这会产生错误的结果:
endaaa tasusumma orderinr
XX00221059842412 150.00 PV04131
XX00221059842412 0.38 PV04131
由于第二行没有 EndToEnd,所以第二行 orderinr 列中应该有空文本:
endaaa tasusumma orderinr
XX00221059842412 150.00 PV04131
XX00221059842412 0.38 null
如何解决这个问题?
可以通过其他方式进行解析e.q。使用 xslt 样式表进行转换或在客户端 ASP.NET 4.6 MVC 如果这更合理。
create temp table t(x xml, nsa text[][]) on commit drop;
insert into t values(
'<?xml version=''1.0'' encoding=''UTF-8''?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
<BkToCstmrStmt>
<Stmt>
<Acct>
<Id>
<IBAN>XX00221059842412</IBAN>
</Id>
</Acct>
<Ntry>
<Amt Ccy="EUR">150.00</Amt>
<NtryDtls>
<TxDtls>
<Refs>
<EndToEndId>PV04131</EndToEndId>
</Refs>
</TxDtls>
</NtryDtls>
</Ntry>
<Ntry>
<Amt Ccy="EUR">0.38</Amt>
<NtryDtls>
<TxDtls>
<Refs>
<AcctSvcrRef>2016080100178214-2</AcctSvcrRef>
</Refs>
</TxDtls>
</NtryDtls>
</Ntry>
</Stmt>
</BkToCstmrStmt>
</Document>
', ARRAY[ARRAY['ns','urn:iso:std:iso:20022:tech:xsd:camt.053.001.02']]);
SELECT
unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Acct/ns:Id/ns:IBAN/text()', x,nsa))::text AS endaaa,
unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Ntry/ns:Amt/text()', x,nsa))::text::numeric AS tasusumma
, unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Ntry/ns:NtryDtls/ns:TxDtls/ns:Refs/ns:EndToEndId/text()', x,nsa))::text AS orderinr
FROM t;
更新
使用 Hannes 的代码回答 returns Postgres 9.1 中的空行如何让它在 9.1 中工作?
也发布在 pgsql.general 邮件列表中。
您需要先提取所有 ns:Ntry 个元素,然后获取每个元素的数量和 EndToEndId:
SELECT
endaaa,
(xpath('ns:Amt/text()', x,nsa))[1]::text::numeric AS tasusumma,
(xpath('ns:NtryDtls/ns:TxDtls/ns:Refs/ns:EndToEndId/text()', x,nsa))[1] AS orderinr
FROM (
SELECT (xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Acct/ns:Id/ns:IBAN/text()', x,nsa))[1] as endaaa,
unnest(xpath('/ns:Document/ns:BkToCstmrStmt/ns:Stmt/ns:Ntry', x,nsa)) as x, nsa
FROM t
) Ntry