0

I have to update XML values stored in an BLOB column in Oracle 11G. The BLOB has stored a comlete XML file in which i have to update some values and save it back as a BLOB. How can i easily SELECT and UPDATE the data wit blob conversion and XMLQUERY AND XMLUPDATE? Any code examples?

Thank you in advance.

Here are some more details:

Here is the ddl of the table:

CREATE TABLE MAPSHEET
(
  MAPSHEETID NUMBER (14,0) NOT NULL,
  NAME VARCHAR2 (64) NOT NULL,
  STRUCTURE BLOB,
)

the xml data in the blob col STRUCTURE

<MapSheet Version="1.0">
    <Frame>
        <JobId>9022165</JobId>
        <LayoutId>24807064</LayoutId>
        <Blocks>
            <Block MapFieldMask="true" CompressText="false" CombineRaster="false">
                <Name>layout</Name>
                <StyleId>24808857</StyleId>
                <LayoutLayers>0 1</LayoutLayers>
                <BlockScale/>
                <JobItemIds/>
            </Block>
            <Block MapFieldMask="true" CompressText="false" CombineRaster="false">
                <Name>karto</Name>
                <StyleId>24809031</StyleId>
                <LayoutLayers>4</LayoutLayers>
                <BlockScale/>
                <JobItemIds>
                    <JobItemId>9083675</JobItemId>
                    <JobItemId>9088148</JobItemId>
                </JobItemIds>
            </Block>
            <Block MapFieldMask="true" CompressText="false" CombineRaster="false">
                <Name>hel</Name>
                <StyleId>24809032</StyleId>
                <LayoutLayers>-</LayoutLayers>
                <BlockScale/>
                <JobItemIds>
                    <JobItemId>9022173</JobItemId>
                    <JobItemId>25403646</JobItemId>
                </JobItemIds>
            </Block><Block MapFieldMask="true" CompressText="false" CombineRaster="false">
                <Name>shade glacier</Name>
                <StyleId>24809041</StyleId>
                <LayoutLayers>-</LayoutLayers>
                <BlockScale/>
                <JobItemIds>
                    <JobItemId>24806040</JobItemId>
                </JobItemIds>
            </Block>
            <Block MapFieldMask="true" CompressText="false" CombineRaster="false">
                <Name>shade</Name>
                <StyleId>24809040</StyleId>
                <LayoutLayers>-</LayoutLayers>
                <BlockScale/>
                <JobItemIds>
                    <JobItemId>24806038</JobItemId>
                </JobItemIds>
            </Block>
        </Blocks>
        <Offset X="0" Y="0"/>
        <Name>DS</Name>
    </Frame></MapSheet>

This simple SELECT to get the data does not work:

SELECT x.MapSheet
FROM XmlTable('/MapSheet') PASSING XmlType(MAPSHEET.STRUCTURE,1)
    COLUMS "XML" VARCHAR2(300) PATH 'MapSheet') AS x;

How can i select/update the desired xml data out of the blob colum?

2 Answers 2

1
create table testxmlBlob (p blob);

Insert some xml document into table.

insert into  testxmlBlob values( utl_raw.cast_to_raw('<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer''s Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book></catalog>')) ;

View inserted xml. xmltype(blob,csid -charset enocoding id '0' is default)

select xmlserialize(document xmltype(p,0)) from  testxmlBlob;  

Use xmlquery to change <description> to <descriptionNew>. it also can be used in update statement update testxmlBlob set p = XMLQuery(....) ...

 select XMLQuery('copy $i := $p1
              modify
              (
             for $j in $i/catalog/book/description
             let $newn := <descriptionNew>newDescription</descriptionNew>
             return replace node $j with $newn)
             return $i             
             ' PASSING xmltype(p,0) AS "p1"     
          RETURNING CONTENT) readable
          ,xmlserialize(document XMLQuery('copy $i := $p1
              modify
              (
             for $j in $i/catalog/book/description
             let $newn := <descriptionNew>newDescription</descriptionNew>
             return replace node $j with $newn)
             return $i             
             ' PASSING xmltype(p,0) AS "p1" 
          RETURNING CONTENT) as BLOB) blob_value
          from  testxmlBlob;  

Other example how to use xmlquery to update

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot!! Everthing fine now!
0

For selecting from XML you can either use ExtractValue(XmlType, XPath) or XmlTable to transform the Xml clob into a queriable table of XML. For BLOB converstion, you should be able to just wrap it with XmlType(blob_value, 1), then you can perform any of the XML related function on it.

SELECT ExtractValue(
          XmlType('<test><node1>value1</node1><node2>value2</node2></test>'), 
                  '/test/node1') as Node1 
FROM dual;

Or using XmlTable

SELECT xt.Node1, xt.Node2
FROM XmlTable('/test/block'
         PASSING XmlType('<test>
<block><node1>value1a</node1><node2>value2a</node2></block>
<block><node1>value1b</node1><node2>value2b</node2></block>
<block><node1>value1c</node1><node2>value2c</node2></block>
</test>')
        COLUMNS
        "Node1"     VARCHAR2(20)   PATH 'node1',
        "Node2"     VARCHAR2(20)   PATH 'node2') AS xt;

Using UpdateXml, assuming the record I am updating has the above XML in a column:

UPDATE MyTable SET xml_data =
UpdateXml(xml_data, '/test/block/node2[text() = "value2b"]/text()', 'value2z')
WHERE data_id = 1;

The above should update the node2 that had the value value2b to now have value2z instead. Which then returns the new XML and assigns it to the column xml_data in the record that matches data_id = 1.

One note, in the above query, it is working with a column that is already of the type XmlType. You are working with a BLOB. I would ask, is there a reason for it being BLOB instead of CLOB or XmlType? If you are storing VARCHAR type data you should really be using one of the latter two types, CLOB if you are storing various VARCHAR data, and XmlType (which is a more specific type of CLOB anyway) if you are storing strictly XML data.

If you are stuck using the BLOB data type you will need to perform a lot of conversions. Using XmlType(blob_data, 1) should get you from BLOB to XmlType, but going back you will likely need to use UTL_RAW.CAST_TO_RAW(xml_data). So the query would become:

UPDATE MyTable SET clob_data =
UTL_RAW.CAST_TO_RAW(
    UpdateXml(XmlType(clob_data, 1), '/test/block/node2[text() = "value2b"]/text()', 'value2z').GetClobVal()
)
WHERE data_id = 1;

Here is a working stand alone example showing the various methods mentioned above:

DECLARE varchar_data    VARCHAR2(500);
        blob_data       BLOB;
        xml_data        XMLType;
        node1Val        VARCHAR(20);
        node2Val        VARCHAR(20);

BEGIN
    select '<test>
<group><node1>value1a</node1><node2>value2a</node2></group>
<group><node1>value1b</node1><node2>value2b</node2></group>
<group><node1>value1c</node1><node2>value2c</node2></group>
<group><node1>value1d</node1><node2>value2d</node2></group>
</test>' into varchar_data from dual;

    select UTL_RAW.CAST_TO_RAW(varchar_data) into blob_data from dual;

    select XmlType(blob_data, 1) into xml_data from dual;
    dbms_output.put_line(xml_data.getClobVal());

    select xt.Node1, xt.Node2
    into node1Val, node2Val
    from XmlTable('/test/group' 
        passing XmlType(blob_data, 1)
        columns Node1     VARCHAR2(20)    path 'node1',
                Node2     VARCHAR2(20)    path 'node2'
        ) xt
    where xt.Node1 = 'value1c';
    dbms_output.put_line('node1Val = ''' || node1Val || ''', node2Val = ''' || node2Val || ''';'); 

    -- Using UpdateXml to update the XML, that will return an XmlType 
    -- so we call GetClobVal() to let CAST_TO_RAW convert to BLOB.
    select UTL_RAW.CAST_TO_RAW(
        UpdateXml(
            XmlType(blob_data, 1), 
            '/test/group/node2[../node1/text() = "value1c"]/text()', 
            'zzzz').GetClobVal()
        ) into blob_data
    from dual; 

    select XmlType(blob_data, 1) into xml_data from dual;
    dbms_output.put_line(xml_data.getClobVal());

    select xt.Node1, xt.Node2
    into node1Val, node2Val
    from XmlTable('/test/group' 
        passing XmlType(blob_data, 1)
        columns Node1     VARCHAR2(20)    path 'node1',
                Node2     VARCHAR2(20)    path 'node2'
        ) xt
    where xt.Node1 = 'value1c';
    dbms_output.put_line('node1Val = ''' || node1Val || ''', node2Val = ''' || node2Val || ''';'); 

END;

5 Comments

Hi, i can't use the ExtractValue command any longer because it's deprecated. So i have to try it with XmlTable in your example. But there is the blob to clob conversion missing and the same for the update statement, the simple wrap around XMLType(blob_value) method is not working. Can you please add the complete syntax for it. Would be great!
@happymapper - Sorry forgot to include the parameter to indicate characterset (1 = USASCII) in the XmlType function.
Your select example is still not working, because the XMLType syntax is still using XML data. The blob is used in our table because this is a default setting of our system and i should not change this.
What do you mean the XmlType is still using XML data? I will update my answer with a working stand alone example.
I've meant that your passing XmlType(....) statement works with pure XML data instead of the needed blob data type. Your stand alone example is perfect. I really appreciate your support and your advice, thank you very much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.