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
Here I leave part of the xml content:
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