简体   繁体   中英

Extracting XML in VBA from Oracle DB

I have an Oracle DB that contains an XML Column called CONTENT of this kind:

<?xml version="1.0"?>
<PAGE>
  <INFO>
    <ID>324374</ID>
    <PAGE>ANE_CSC</PAGE>
  </INFO>
  <CAMPS>
    <CAMP KEY_CAMP="ACCESS_CONTROL">456675</CAMP>
    <CAMP KEY_CAMP="IDEN_ANAG">1458</CAMP>...
  </CAMPS>
</PAGE>

I'm trying to extract the IDEN_ANAG value (so: 1458 ) in a Excel cell, however I've no idea how to elaborate XML data correctly in VBA.

I have tried a few things (commands like getStringVal(), getClob(), EXTRACT() ) and cannot figure out a solution that would work.

This is what I'm currently trying to do:

Cmd.CommandText = "select XMLTYPE('<CAMP>'||CONTENT||'</CAMP>').getStringVal() from table WHERE ID = 324374
Set rs = Cmd.Execute()

Do While Not rs.EOF
    WSP1.Cells(CellWrite, 1).Value = rs.Fields(0).Value
    
    CellWrite = CellWrite + 1
    rs.MoveNext
Loop

I know that the code above isn't actually extracting the specific ID, but I'm fairly desparate to at least start with extracting the whole XML and then trying to find a solution for just specific part of it.

While I'm almost sure that I'm just making a mistake in the code, I've tried several different results based on internet searches, using different functions etc and I've always run into errors like Runtime error or the code above gives me the error as Runtime error: Character string buffer too small .

Any suggestions on how to extract the specific data would be appreciated.

Use a proper XML parser. You can either use the query:

SELECT iden_anag
FROM   table_name t
       CROSS APPLY XMLTABLE(
         '/PAGE/CAMPS'
         PASSING XMLTYPE( t.content )
         COLUMNS
           iden_anag NUMBER PATH './CAMP[@KEY_CAMP="IDEN_ANAG"]'
       )
WHERE  id = 324374

or

SELECT XMLQUERY(
         '/PAGE/CAMPS/CAMP[@KEY_CAMP="IDEN_ANAG"]/text()'
         PASSING XMLTYPE( content )
         RETURNING CONTENT
       ) AS iden_anag
FROM   table_name
WHERE  id = 324374

Which, for your sample data:

CREATE TABLE table_name ( id NUMBER, content CLOB );

INSERT INTO table_name ( id, content ) VALUES (
  324374,
'<?xml version="1.0"?>
<PAGE>
  <INFO>
    <ID>324374</ID>
    <PAGE>ANE_CSC</PAGE>
  </INFO>
  <CAMPS>
    <CAMP KEY_CAMP="ACCESS_CONTROL">456675</CAMP>
    <CAMP KEY_CAMP="IDEN_ANAG">1458</CAMP>...
  </CAMPS>
</PAGE>'
);

Both output:

 |  IDEN_ANAG |  |  --------: |  |  1458 |

db<>fiddle here

It is an Oracle error and appears when you try to put some big string into VARCHAR datatype.

You can check this documentation article , section "Selecting XML Data Using XMLType Methods":

You can select XMLType data using PL/SQL, C, or Java. You can also use the XMLType methods getClobVal() , getStringVal() , getNumberVal() , and getBlobVal(csid) to retrieve XML data as a CLOB , VARCHAR , NUMBER , and BLOB value, respectively.

So looks like your data is too big to fit in VARCHAR that getStringVal() returns, and you need to use getClobVal() .

Also there's no need to create XML data by concatenation since it cannot handle all the serialization specifics (like symbols used in XML should be converted) and you can also face the same limitation of VARCHAR length on concatenation. You need XMLElement function for this:

 select xmlelement("Current_date", sysdate) as date_xml, xmlelement("SpecialSymbols", 'Symbols > and < need conversion') as spec_symbols_xml from dual
 DATE_XML |  SPEC_SYMBOLS_XML:-------------------------------------- |:--------------------------------------------------------------------- <Current_date>2021-03-05</Current_date> |  <SpecialSymbols>Symbols &gt;  and &lt; need conversion</SpecialSymbols>

db<>fiddle here

You can chech a bunch of XML manipulation functions to build XML, so use them instead of string manipulations. For example, get query results as XML:

 select dbms_xmlgen.getxml('select object_name, object_type from all_objects where rownum < 3') as result_clob from dual
 |  RESULT_CLOB | |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |  |  <?xml version="1.0"?><br><ROWSET><br> <ROW><br> <OBJECT_NAME>ORA$BASE</OBJECT_NAME><br> <OBJECT_TYPE>EDITION</OBJECT_TYPE><br> </ROW><br> <ROW><br> <OBJECT_NAME>DUAL</OBJECT_NAME><br> <OBJECT_TYPE>TABLE</OBJECT_TYPE><br> </ROW><br></ROWSET><br> | 

db<>fiddle here

But it is better to do all MXL manipulations in the database and retrieve plain results to VBA.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM