从位于Clob字段Oracle

时间:2016-03-03 20:59:10

标签: xml oracle

我是XML新手,我想从具有CLOB列类型的表中加载的XML中提取文本。

由于有叶子节点,我无法得到线索.XML非常大,这只是一个片段,如果我可以解决这个问题,我将尝试为整个XML实现。

我有以下查询,但我没有获得服务ID的任何值

   SELECT *
    FROM XML_T y
    ,XMLTABLE(XMLNAMESPACES('all the name spaces'),
                    '//e:DocumentServiceID'
                    --/e:DocumentHeader/e:DocumentServiceID'
                        PASSING XMLTYPE.createxml(y.xmlty) 
                        COLUMNS service_id varchar2(200) path '@DocumentServiceID'
                              /*  factext varchar2(100) path '@FacText',
                                fac varchar2(100) path '@Fac',
                                st_name varchar2(100) path './StreetName',
                                zipcode varchar2(10) path './PostalCode',
                            */
);

我已将下面的内容放入表格

<?XML VERSION="1.0" encoding="UTF-8"?>
<E:EnDatDoc xmlns:ext="http://qbc.net/de/City/A-Ex/1.0" xmlns:df="http://xyz.ht.net/yy/Asset/1.0" xmlns:nc="http://pol.org/ni-core/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:E="http://www.yup.net/enterprise">
    <E:DocumentHeader>
     <E:DocumentServiceID>A_PUSH</E:DocumentServiceID>
     </E:DocumentHeader>
        <E:DocumentBody>
            <df:PropertyRecord>
                    <ext:Facility>
                                <nc:FacText>A9</nc:FacText>
                                <ext:Fac>One St</ext:Fac>
                                <nc:Facility>
                                    <nc:LocationAddress>
                                        <nc:Addr>
                                            <nc:Street>
                                                <nc:StreetName>18 STR</nc:StreetName>
                                            </nc:Street>
                                        <nc:PostalCode>07854</nc:PostalCode>
                                        </nc:Addr>
                                    </nc:LocationAddress>
                                </nc:Facility>
                            <ext:Item>
                                <nc:MeasureText>40.99</nc:MeasureText>
                                <nc:length>SF</nc:length>
                            </ext:Item>
                            <ext:Gross>
                                <nc:MeasureText>90.00</nc:MeasureText>
                                <nc:Length>SF</nc:Length>
                            </ext:Gross>
                            <nc:ItemWidth>
                                <nc:MeasureText>24.83</nc:MeasureText>
                                <nc:length>FT</nc:length>
                            </nc:ItemWidth>
                            <ext:Irregular>FALSE</ext:Irregular>
                            <ext:Floors>1</ext:Floors>
                        <ext:Cons>
                            <nc:StartDate>
                                <nc:YEAR>1977</nc:YEAR>
                            </nc:StartDate>
                        </ext:Cons>
                        <ext:Conflg>TRUE</ext:Conflg>
                        <ext:Tax>
                            <ext:Classtext>1</ext:Classtext>
                            <ext:Cdesc>1 - 3 Units</ext:Cdesc>
                        </ext:Tax>
                    </ext:Facility>
            </df:PropertyRecord>
        </E:DocumentBody>
     </E:EnDatDoc>

1 个答案:

答案 0 :(得分:1)

You need to give the full path to each (leaf) node you want to extract, relative to the node identified by the XPath. You also need to refer to the element, not an attribute (with the '@ syntax you were using).

select x.*
from xml_t y
cross join xmltable(
  xmlnamespaces('http://qbc.net/de/City/A-Ex/1.0' as "ext",
    'http://xyz.ht.net/yy/Asset/1.0' as "df",
    'http://pol.org/ni-core/2.0' as "nc",
    'http://www.yup.net/enterprise' as "E"),
  '/E:EnDatDoc'
  passing xmltype.createxml(y.xmlty) 
  columns service_id varchar2(10) path 'E:DocumentHeader/E:DocumentServiceID',
    factext varchar2(10) path 'E:DocumentBody/df:PropertyRecord/ext:Facility/nc:FacText',
    fac varchar2(10) path 'E:DocumentBody/df:PropertyRecord/ext:Facility/ext:Fac',
    st_name varchar2(10) path 'E:DocumentBody/df:PropertyRecord/ext:Facility/nc:Facility/nc:LocationAddress/nc:Addr/nc:Street/nc:StreetName',
    zipcode varchar2(10) path 'E:DocumentBody/df:PropertyRecord/ext:Facility/nc:Facility/nc:LocationAddress/nc:Addr/nc:PostalCode'
) x;

SERVICE_ID FACTEXT    FAC        ST_NAME    ZIPCODE  
---------- ---------- ---------- ---------- ----------
A_PUSH     A9         One St     18 STR     07854     

And then extend that for all the other nodes/columns you want to extract.

You could cheat and use wildcard namespaces and paths:

select x.*
from xml_t y
cross join xmltable(
  '/'
  passing xmltype.createxml(y.xmlty) 
  columns service_id varchar2(10) path '//*:DocumentServiceID',
    factext varchar2(10) path '//*:FacText',
    fac varchar2(10) path '//*:Fac',
    st_name varchar2(10) path '//*:StreetName',
    zipcode varchar2(10) path '//*:PostalCode'
) x;

but you may have namespace clashes (as you do with ext:Facility and nc:Facility) which will cause problems or break at some point, and unless this is an ad hoc one-off query it would be much better to be explicit and self-documenting. You and anyone reading the query can see where you're expecting each bit of information to come from.

You could also make the XPath flatten out the structure by constructing new elements which have all the information you want as attributes, but it's probably more difficult and less clear.