【问题标题】:xml nodes with special characters带有特殊字符的xml节点
【发布时间】:2018-12-04 20:38:10
【问题描述】:

我有这样的 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 节点中,它们具有我无法处理的特殊字符 (:)。有人可以帮我解决这个问题吗?

真正的 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>

【问题讨论】:

  • 生成 XML 的原因是什么?
  • 这是我在此处共享的示例 XML 文件,以便轻松解释我所面临的错误。
  • 看起来样本来自dbms_xmlgen,带有一个奇怪的setRowTag() 值。据我所知,您不能将冒号作为实际节点名称的一部分,因为它表示错误消息中提到的事情之一。您的真实 XML 是否有命名空间(xmlns 嵌入任何节点的值)?不清楚您的真实 XML 是否看起来像这样,或者您是否通过过度简化隐藏了真正的问题。如果你不能分享你真正的 XML,请至少使用结构相同的东西......
  • 好的明白了,我来分享一下真正的XML文件
  • 好的,你真正的查询呢?您可能只需要声明命名空间(如 here,尽管您的命名空间称为 SOAP-ENV 而不是 soapenv)。

标签: oracle


【解决方案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$
...

但我认为最好是明确的。

【讨论】:

  • 完美.. 非常感谢您的解决方案和有用的信息。
猜你喜欢
  • 2021-02-12
  • 2011-07-19
  • 1970-01-01
  • 2011-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
相关资源
最近更新 更多