【问题标题】:Parsing XML containing name space解析包含名称空间的 XML
【发布时间】:2018-12-30 13:45:14
【问题描述】:

我在解析包含名称空间的 XML 时遇到问题。

这是我的 XML 结构(截断,带有修改的数据):

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02 ./camt.053.001.02.xsd">
    <BkToCstmrStmt>
        <Stmt>
            <Ntry>
                <Amt Ccy="EUR">0.0</Amt>
                <CdtDbtInd>CCCC</CdtDbtInd>
                <Sts>BBBB</Sts>
                <BookgDt>
                    <Dt>2011-01-01</Dt>
                </BookgDt>
                <ValDt>
                    <Dt>2011-01-01</Dt>
                </ValDt>
                <AcctSvcrRef>325569685ASDAS</AcctSvcrRef>
                <BkTxCd>
                    <Prtry>
                        <Cd>NOTPROVIDED</Cd>
                    </Prtry>
                </BkTxCd>
                <NtryDtls>
                    <TxDtls>
                        <Refs>
                            <EndToEndId>DD545454545-54545-54</EndToEndId>
                            <TxId>46545445G5GG54DD5S</TxId>
                        </Refs>
                        <RltdPties>
                            <Dbtr>
                                <Nm>TEST</Nm>
                                <PstlAdr>
                                    <Ctry>JJ</Ctry>
                                    <AdrLine>TEST ADD</AdrLine>
                                    <AdrLine>TEST ADD2</AdrLine>
                                </PstlAdr>
                            </Dbtr>
                            <DbtrAcct>
                                <Id>
                                    <IBAN>000000000000000</IBAN>
                                </Id>
                            </DbtrAcct>
                            <Cdtr>
                                <Nm>TEST NAME</Nm>
                                <PstlAdr>
                                    <Ctry>JJ</Ctry>
                                    <AdrLine>TEST ADD3</AdrLine>
                                    <AdrLine>TEST ADD4</AdrLine>
                                </PstlAdr>
                            </Cdtr>
                            <CdtrAcct>
                                <Id>
                                    <IBAN>22222222222222</IBAN>
                                </Id>
                            </CdtrAcct>
                        </RltdPties>
                        <Purp>
                            <Cd>IIII</Cd>
                        </Purp>
                        <RmtInf>
                            <Strd>
                                <CdtrRefInf>
                                    <Ref>GG56565656565656</Ref>
                                </CdtrRefInf>
                                <AddtlRmtInf>TEST TEST 123</AddtlRmtInf>
                            </Strd>
                        </RmtInf>
                        <RltdDts>
                            <IntrBkSttlmDt>2011-01-01</IntrBkSttlmDt>
                        </RltdDts>
                    </TxDtls>
                </NtryDtls>
            </Ntry>
        </Stmt>
    </BkToCstmrStmt>
</Document>

如果根元素没有命名空间 (),这是我使用的代码:

DECLARE       
      l_clob CLOB;
      l_bfile  BFILE := BFILENAME('XML_IMPORT', 'test_import.xml');
      l_dest_offset   INTEGER := 1;
      l_src_offset    INTEGER := 1;
      l_bfile_csid    NUMBER  := 0;
      l_lang_context  INTEGER := 0;
      l_warning       INTEGER := 0;
      l_xml           xmltype;
BEGIN
      DBMS_LOB.createtemporary (l_clob, TRUE);
      DBMS_LOB.fileopen(l_bfile, DBMS_LOB.file_readonly);

      DBMS_LOB.loadclobfromfile (
        dest_lob      => l_clob,
        src_bfile     => l_bfile,
        amount        => DBMS_LOB.lobmaxsize,
        dest_offset   => l_dest_offset,
        src_offset    => l_src_offset,
        bfile_csid    => l_bfile_csid ,
        lang_context  => l_lang_context,
        warning       => l_warning);
      DBMS_LOB.fileclose(l_bfile);          

      l_xml := xmltype(l_clob);

     BEGIN
      FOR r IN (
        SELECT ExtractValue(Value(p),'/Ntry/Amt/text()') as TEMP_COL1
              ,ExtractValue(Value(p),'/Ntry/Amt/@Ccy/text()') as TEMP_COL2
              ,ExtractValue(Value(p),'/Ntry/ValDt/Dt/text()') as TEMP_COL3
              ,ExtractValue(Value(p),'/Ntry/BookgDt/Dt/text()') as TEMP_COL4

        FROM    TABLE(XMLSequence(Extract(l_xml,'/Document/BkToCstmrStmt/Stmt/Ntry'))) p
        ) 
        LOOP
            dbms_output.put_line('Some value 1: ' ||  r.TEMP_COL1);
            dbms_output.put_line('Some value 2: ' ||  r.TEMP_COL2);
            dbms_output.put_line('Some value 3: ' ||  r.TEMP_COL3);
            dbms_output.put_line('Some value 4: ' ||  r.TEMP_COL4);
        END LOOP;
    END;     
END;

我想知道如何修改我的代码以使用名称空间。 Google 提供了一些示例,但到目前为止,我还没有将它们实施到我的解决方案中。

【问题讨论】:

    标签: sql xml oracle plsql xml-parsing


    【解决方案1】:

    我相信您需要将命名空间传递给 Extract()ExtractValue() 函数,例如

    FOR r IN (
        SELECT ExtractValue(Value(p),'/Ntry/Amt/text()', 'xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02"') as TEMP_COL1
              ,ExtractValue(Value(p),'/Ntry/Amt/@Ccy','xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02"') as TEMP_COL2
              ,ExtractValue(Value(p),'/Ntry/ValDt/Dt/text()','xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02"') as TEMP_COL3
              ,ExtractValue(Value(p),'/Ntry/BookgDt/Dt/text()','xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02"') as TEMP_COL4
    
        FROM    TABLE(XMLSequence(Extract(l_xml,'/Document/BkToCstmrStmt/Stmt/Ntry', 'xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02"'))) p
      ) 
      LOOP
          dbms_output.put_line('Some value 1: ' ||  r.TEMP_COL1);
          dbms_output.put_line('Some value 2: ' ||  r.TEMP_COL2);
          dbms_output.put_line('Some value 3: ' ||  r.TEMP_COL3);
          dbms_output.put_line('Some value 4: ' ||  r.TEMP_COL4);
      END LOOP;   
    

    我认为没有办法为 ExtractValue 函数指定默认命名空间,所以我个人的偏好是做这样的事情来避免重复声明命名空间:

    FOR r IN (
        SELECT p.temp_col1,
               p.temp_col2,
               p.temp_col3,
               p.temp_col4
        FROM   xmltable(
                 --define a default namespace to be used for all values
                 xmlnamespaces(
                   DEFAULT 'urn:iso:std:iso:20022:tech:xsd:camt.053.001.02'
                 ),
    
                 --define an xpath expression for the values you want to extract
                 '/Document/BkToCstmrStmt/Stmt/Ntry'
    
                 --pass the xml type in here
                 PASSING l_xml
    
                 --declare the columns you would like to extract and the formats they are expected to be in
                 COLUMNS
                   temp_col1 VARCHAR2(128) path '/Ntry/Amt/text()',
                   temp_col2 VARCHAR2(128) path '/Ntry/Amt/@Ccy',
                   temp_col3 VARCHAR2(128) path '/Ntry/ValDt/Dt/text()',
                   temp_col4 VARCHAR2(128) path '/Ntry/BookgDt/Dt/text()'
               ) p
      )
      LOOP
        dbms_output.put_line('Some value 1: ' ||  r.temp_col1);
        dbms_output.put_line('Some value 2: ' ||  r.temp_col2);
        dbms_output.put_line('Some value 3: ' ||  r.temp_col3);
        dbms_output.put_line('Some value 4: ' ||  r.temp_col4);
      END LOOP;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多