带有特殊字符的xml节点

时间:2016-12-22 15:40:38

标签: oracle

我有这样的testing.xml文件:

<ROWSET>
<ROW_DATA:TYPE>
<ID>1</ID>
<TEXT>This is some text</TEXT>
</ROW_DATA:TYPE>
<ROW_DATA:TYPE>
<ID>2</ID>
<TEXT>This is some more text</TEXT>
</ROW_DATA:TYPE>
<ROW_DATA:TYPE>
<ID>3</ID>
<TEXT>This is some other text</TEXT>
</ROW_DATA:TYPE>
<ROW_DATA:TYPE>
<ID>4</ID>
<TEXT>This is also some text</TEXT>
</ROW_DATA:TYPE>
</ROWSET>

我将这个testing.xml文件加载到表test_xml:

INSERT INTO test_xml VALUES( 
xmltype(bfilename('TESTING','testing.xml'),nls_charset_id('AL32UTF8')));
commit;

之后,我尝试编写代码以从xml表中获取数据:

select grp1.* 
from 
test_xml t
,xmltable('//ROWSET'
          passing t.SYS_NC_ROWINFO$
          columns row_1     xmltype   path  '/ROWSET/ROW_DATA:TYPE'
         ) grp0

,xmltable('/ROW_DATA:TYPE'
          passing grp0.row_1
          columns ID_1    NUMBER(10)  PATH 'ID'
                  ,TEXT_1    VARCHAR2(40)  PATH 'TEXT'
         ) grp1 
;

最后,它出现了一条错误消息:

ORA-19228: XPST0008 - undeclared identifier: prefix 'ROW_DATA' local-name 'ROW_DATA:TYPE'
19228. 00000 -  "XP0008 - undeclared identifier: prefix '%s' local-name '%s'"
*Cause:    The given identifier refers to either a type name, function name, namespace prefix, or variable name that is not defined in the static context.
*Action:   Fix the expression to remove the identifier, or declare the appropriate variable, type, function or namespace.
Error at Line: 17 Column: 2

因此,在其中一个XML节点中,它们具有我无法处理的特殊字符(:)。有人可以帮我吗?

Real XML文件(来自网络服务)是:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header>
      <MultiSpeakMsgHeader AppName="CD" AppVersion="3.0" CSUnits="feet" Company="xxxxx" LastSent="123455" ObjectsRemaining="1" xmlns="http://www.multispeak.org/Version_3.0"/>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body>
      <GetReadingsByDateResponse>
         <GetReadingsByDateResult>
            <meterRead>
               <meterNo>10227</meterNo>
               <deviceID>2</deviceID>
               <readingDate>2016-12-18T06:15:00.339Z</readingDate>
               <posKWh>85893</posKWh>
               <kW>2.8018</kW>
               <phase>AB</phase>
               <readingValues>
                  <readingValue>
                     <units>kWh</units>
                     <value>85892.586</value>
                     <readingValueType>Energy</readingValueType>
                     <dateTime>2016-12-18T06:15:00.339Z</dateTime>
                  </readingValue>
                  <readingValue>
                     <units>kW</units>
                     <value>2.504</value>
                     <readingValueType>Current demand</readingValueType>
                     <dateTime>2016-12-18T06:15:00.339Z</dateTime>
                  </readingValue>
                  <readingValue>
                     <units>kW</units>
                     <value>2.8018</value>
                     <readingValueType>Max demand</readingValueType>
                     <dateTime>2016-12-18T06:15:00.339Z</dateTime>
                  </readingValue>
                  <readingValue>
                     <units>V</units>
                     <value>244.1</value>
                     <readingValueType>Current Voltage</readingValueType>
                     <dateTime>2016-12-18T06:15:00.339Z</dateTime>
                  </readingValue>
                  <readingValue>
                     <units>V</units>
                     <value>244.1</value>
                     <readingValueType>Current Voltage Phase A</readingValueType>
                     <dateTime>2016-12-18T06:15:00.339Z</dateTime>
                  </readingValue>
                  <readingValue>
                     <units>V</units>
                     <value>0.3</value>
                     <readingValueType>Current Voltage Phase B</readingValueType>
                     <dateTime>2016-12-18T06:15:00.339Z</dateTime>
                  </readingValue>
               </readingValues>
            </meterRead>
         </GetReadingsByDateResult>
      </GetReadingsByDateResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

1 个答案:

答案 0 :(得分:1)

错误是因为您的查询未在XMLTable调用中声明命名空间。 XML具有在SOAP-ENV:Envelope节点中声明的名称空间,xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

您可以向XMLTable调用添加名称空间声明,例如:

select grp1.* 
from 
test_xml t
,xmltable(xmlnamespaces ('http://schemas.xmlsoap.org/soap/envelope' AS "SOAP-ENV"),
          '/SOAP-ENV:Envelope'
          passing t.SYS_NC_ROWINFO$
          columns row_1     xmltype   path  'SOAP-ENV:Body'
         ) grp0
,xmltable(xmlnamespaces ('http://schemas.xmlsoap.org/soap/envelope' AS "SOAP-ENV"),
          '/SOAP-ENV:Body'
          passing grp0.row_1
          columns ID_1    NUMBER(10)  PATH 'ID'
                  ,TEXT_1    VARCHAR2(40)  PATH 'TEXT'
         ) grp1 

或者您的示例数据更有用的示例:

select x1.meterNo,
  from_tz(to_timestamp(x1.readingDate, 'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"'), 'UTC') as readingDate,
  x2.readingValueType, x2.value, x2.units 
from test_xml t
cross join xmltable(
  xmlnamespaces ('http://schemas.xmlsoap.org/soap/envelope/' AS "SOAP-ENV"),
  '/SOAP-ENV:Envelope/SOAP-ENV:Body/GetReadingsByDateResponse/GetReadingsByDateResult/meterRead'
  passing t.SYS_NC_ROWINFO$
  columns meterNo number path 'meterNo',
    readingDate varchar2(24) path 'readingDate',
    readingValues xmltype path  'readingValues'
) x1
cross join xmltable(
  '/readingValues/readingValue'
  passing x1.readingValues
  columns readingValueType varchar2(30) path 'readingValueType',
    value number path 'value',
    units varchar2(3) path 'units'
) x2;

   METERNO READINGDATE                      READINGVALUETYPE                    VALUE UNI
---------- -------------------------------- ------------------------------ ---------- ---
     10227 18-DEC-16 06.15.00.339000000 UTC Energy                          85892.586 kWh
     10227 18-DEC-16 06.15.00.339000000 UTC Current demand                      2.504 kW 
     10227 18-DEC-16 06.15.00.339000000 UTC Max demand                         2.8018 kW 
     10227 18-DEC-16 06.15.00.339000000 UTC Current Voltage                     244.1 V  
     10227 18-DEC-16 06.15.00.339000000 UTC Current Voltage Phase A             244.1 V  
     10227 18-DEC-16 06.15.00.339000000 UTC Current Voltage Phase B                .3 V  

请注意,在这种情况下,您不需要在第二个XMLTable中声明名称空间,因为您引用的节点没有SOAP-ENV前缀。

你可以欺骗并使用通配符:

...
from test_xml t
cross join xmltable(
  '/*:Envelope/*:Body/GetReadingsByDateResponse/GetReadingsByDateResult/meterRead'
  passing t.SYS_NC_ROWINFO$
...

或忽略带有前缀的节点,如果您不需要直接来自这些节点的数据,只有他们的孩子:

...
from test_xml t
cross join xmltable(
  '//meterRead'
  passing t.SYS_NC_ROWINFO$
...

但我认为明白这一点会更好。