Home > database >  SQL Oracle how to extract xml tag content in a blob column
SQL Oracle how to extract xml tag content in a blob column

Time:07-03

There is an xml that is in a column of type BLOB (in oracle) and I need to access a certain tag from that xml. Until then I can retrieve the column this way:

SELECT TRIM(UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(my_column_blob, 1024))) as tag_name_xml
FROM my_table

the return is like this: enter image description here

Here I leave part of the xml content: enter image description here

How do I return the value/content of the cUF or cCT tag? I would like the help of people with more knowledge, please.

CodePudding user response:

You can first convert your BLOB data into CLOB type, and then extract the tags you need. Here are two functions that will, hopefully, solve your problem:

FUNCTION BLOB2CLOB(mBLOB IN BLOB) 
    RETURN CLOB IS
BEGIN
    Declare
        mCLOB   CLOB;
        mDestOffSet     INTEGER;
        mSrcOffSet      INTEGER;
        mBLOBCSID       INTEGER;
        mLangCntx       INTEGER;
        mWarn           INTEGER;
    Begin
        mDestOffSet := 1;
        mSrcOffSet := 1;
        mBLOBCSID := 0;
        mLangCntx := 0;
        mWarn := 0;
        DBMS_LOB.CreateTemporary(mCLOB, TRUE);
        DBMS_LOB.ConvertToClob(mCLOB, mBLOB, DBMS_LOB.GetLength(mBLOB), mDestOffSet, mSrcOffSet, mBLOBCSID, mLangCntx, mWarn);
        RETURN(mCLOB);
    End;
END BLOB2CLOB;
--
FUNCTION Get_SOAP_PartCLOB(mCLOB IN CLOB, mTag IN VARCHAR2) RETURN CLOB 
  IS
BEGIN
    Declare
        wrkCLOB         CLOB;
    myStart       NUMBER(10) := 0;
    myEnd         NUMBER(10) := 0;
    myLength      NUMBER(10) := 0;
    toErase       NUMBER(10) := 0;
    Begin
    DBMS_LOB.CreateTemporary(wrkCLOB, True);
    DBMS_LOB.COPY(wrkCLOB, mCLOB, DBMS_LOB.GETLENGTH(mCLOB));
    --
    myStart := DBMS_LOB.InStr(wrkCLOB, mTag, 1, 1)   Length(mTag) - 1;
    myEnd := DBMS_LOB.InStr(wrkCLOB, SubStr(mTag, 1, 1) || '/' || SubStr(mTag, 2));
    myLength := DBMS_LOB.GetLength(wrkCLOB);
    
    DBMS_LOB.ERASE(wrkCLOB, myStart, 1);
    toErase := myLength - myEnd   1;

    DBMS_LOB.ERASE(wrkCLOB, toErase, myEnd);
    
    wrkCLOB := REPLACE(wrkCLOB, ' ', '');

        RETURN(wrkCLOB);
    End;
END Get_SOAP_PartCLOB;

You can use it like this:

SELECT 
    Get_SOAP_PartCLOB(BLOB2CLOB(YOUR_BLOB_COL), 'your_tag_in_clob') as "TAG_COL_ALIAS"
FROM
    YOUR_TABLE

I use the second function Get_SOAP_PartCLOB() to get some pretty big B64 data out of the soap envelope response from certain web services. That's why the return type is CLOB. You can cast the returned value to something else or make your own adjustments to the function.

CodePudding user response:

Use XMLTYPE and XMLTABLE:

SELECT x.c
FROM   table_name t
       CROSS APPLY XMLTABLE(
         '/a/b/c'
         PASSING XMLTYPE(t.value, 1)
         COLUMNS
           c VARCHAR2(200) PATH './text()'
       ) x

Or XMLQUERY:

SELECT XMLQUERY('/a/b/c/text()' PASSING XMLTYPE(value, 1) RETURNING CONTENT) AS c
FROM   table_name

Which, for the sample data:

CREATE TABLE table_name (value BLOB);

INSERT INTO table_name (value)
VALUES ( UTL_RAW.CAST_TO_RAW( '<a><b><c>something</c></b></a>' ) );

Both output:

C
something

db<>fiddle here

  • Related