简体   繁体   English

从 Oracle DB 中提取 VBA 中的 XML

[英]Extracting XML in VBA from Oracle DB

I have an Oracle DB that contains an XML Column called CONTENT of this kind:我有一个 Oracle DB,其中包含一个名为CONTENT的 XML 列:

<?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.我正在尝试在 Excel 单元格中提取IDEN_ANAG值(因此: 1458 ),但是我不知道如何在 Z6E3EC7E6A9F6007B4838FC0EEZA 中正确详细说明 XML 数据。

I have tried a few things (commands like getStringVal(), getClob(), EXTRACT() ) and cannot figure out a solution that would work.我已经尝试了一些东西( getStringVal(), getClob(), EXTRACT()等命令),但无法找到可行的解决方案。

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.我知道上面的代码实际上并没有提取特定的 ID,但我非常绝望,至少从提取整个 XML 开始,然后尝试为其中的特定部分找到解决方案。

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 .虽然我几乎可以肯定我只是在代码中犯了一个错误,但我已经根据互联网搜索尝试了几种不同的结果,使用不同的功能等,我总是遇到像Runtime error或上面的代码给出的错误我的错误是Runtime error: Character string buffer too small

Any suggestions on how to extract the specific data would be appreciated.任何有关如何提取特定数据的建议将不胜感激。

Use a proper XML parser.使用正确的 XML 解析器。 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: output:

 | | IDEN_ANAG | IDEN_ANAG | | | --------: | --------: | | | 1458 |第1458章

db<>fiddle here db<> 在这里摆弄

It is an Oracle error and appears when you try to put some big string into VARCHAR datatype.这是一个 Oracle 错误,当您尝试将一些大字符串放入VARCHAR数据类型时出现。

You can check this documentation article , section "Selecting XML Data Using XMLType Methods":您可以查看此文档文章,“使用 XMLType 方法选择 XML 数据”部分:

You can select XMLType data using PL/SQL, C, or Java.您可以使用 PL/SQL、C 或 Java 来 select XMLType 数据。 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.您还可以使用 XMLType 方法getClobVal()getStringVal()getNumberVal()getBlobVal(csid)将 XML 数据分别检索为CLOBVARCHARNUMBERBLOB值。

So looks like your data is too big to fit in VARCHAR that getStringVal() returns, and you need to use getClobVal() .因此,看起来您的数据太大而无法放入getStringVal()返回的VARCHAR中,您需要使用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.此外,无需通过串联创建 XML 数据,因为它无法处理所有序列化细节(如 XML 中使用的符号应转换),并且您也可能面临串联时VARCHAR长度的相同限制。 You need XMLElement function for this:为此,您需要XMLElement function:

 select xmlelement("Current_date", sysdate) as date_xml, xmlelement("SpecialSymbols", 'Symbols > and < need conversion') as spec_symbols_xml from dual
 DATE_XML | DATE_XML | SPEC_SYMBOLS_XML:-------------------------------------- |:--------------------------------------------------------------------- <Current_date>2021-03-05</Current_date> | SPEC_SYMBOLS_XML:-------------------------- |:-------- -------------------------------------------------- ----------- <Current_date>2021-03-05</Current_date> | <SpecialSymbols>Symbols &gt; <特殊符号>符号 &gt; and &lt;和 &lt; need conversion</SpecialSymbols>需要转换</SpecialSymbols>

db<>fiddle here db<> 在这里摆弄

You can chech a bunch of XML manipulation functions to build XML, so use them instead of string manipulations.您可以检查一堆XML 操作函数来构建 XML,因此请使用它们而不是字符串操作。 For example, get query results as XML:例如,查询结果为 XML:

 select dbms_xmlgen.getxml('select object_name, object_type from all_objects where rownum < 3') as result_clob from dual
 | | RESULT_CLOB |结果_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> | <?xml version="1.0"?><br><ROWSET><br> <ROW><br> <OBJECT_NAME>ORA$BASE</OBJECT_NAME><br> <OBJECT_TYPE>版本</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 db<> 在这里摆弄

But it is better to do all MXL manipulations in the database and retrieve plain results to VBA.但最好在数据库中执行所有 MXL 操作并将纯结果检索到 VBA。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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