XML 在 Oracle 中解析

XML Parsing in Oracle

我正在尝试解析 XML 文本。它存储在 table t_testxml 列的 xml_data 中,它是 CLOB 类型。

xml 看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<defaultmpftest:defaultmpftest xmlns:defaultmpftest="http://test.com"
 test_id = "1231"
 test_name = "name_test">
</mpftestdata:additionalLinkUrl xmlns:mpftestdata="http://test2.com"/>
</defaultmpftest:defaultmpftest>

如何提取 test_id 和 test_name 的值?

我试过了:

Select extract(xmltype.createxml(t.xml_data),'//defaultmpftest:defaultmpftest/@test_id').getStringVal() from t_testxml t;

但是没有用。我收到以下错误:

ORA-31011: XML Parsing failed
LPX-00601: Invalid token in defaultmpftest:defaultmpftest/@test_id 

你能给我一些关于这件事的建议吗?

谢谢!

XML格式不正确,尝试

<mpftestdata:additionalLinkUrl xmlns:mpftestdata="http://test2.com" />

<mpftestdata:additionalLinkUrl xmlns:mpftestdata="http://test2.com"></mpftestdata>

正如 Wernfried Domscheit 正确指出的那样:您的 XML 格式不正确。对于格式不正确的 XMLs ,无法以常规方式提取其信息。仅仅是因为常规方法适用于 XML;而你的 "XML" 并不是真正的 XML。

那我们试试非常规的方法吧...

with t_testxml as (
    select q'{<?xml version="1.0" encoding="UTF-8"?>
<defaultmpftest:defaultmpftest xmlns:defaultmpftest="http://test.com"
 test_id = "1231"
 test_name = "name_test">
</mpftestdata:additionalLinkUrl xmlns:mpftestdata="http://test2.com"/>
</defaultmpftest:defaultmpftest>}' as xml_data
    from dual
)
select xmlcast(xmlparse(content regexp_substr(T.xml_data, '<defaultmpftest:defaultmpftest[^>]+')||' />').extract('*/@test_id') as integer) as test_id
from t_testxml T
;

问题中显示的 XML 无效,如果将其传递给 XMLType,将导致 "LPX-00231: invalid character" 错误。所以这不是您实际使用的字符串。我假设是在发布问题时出现错字,而您实际上收到了您声称的 "LPX-00601: Invalid token" 错误。因此,我将基于该假设和没有该拼写错误的字符串。

extract is deprecated;但即便如此,要在此处使用它(使用更正的原始 XML),您需要使用可选的第三个参数指定名称空间:

select extract(xmltype.createxml(t.xml_data),
  '//defaultmpftest:defaultmpftest/@test_id',
  'xmlns:defaultmpftest="http://test.com"').getStringVal()
from t_testxml t;

EXTRACT(XMLTYPE.CREATEXML(T.XML_DATA),'//DEFAULTMPFTEST:DEFAULTMPFTEST/@TEST_ID','XMLNS:DEFAULTMPFTEST="HTTP://TEST.COM"').GETSTRINGVAL()
-----------------------------------------------------------------------------------------------------------------------------------------
1231

您可以使用 XMLQuery:

而不是使用已弃用的函数
select xmlquery(
  'declare namespace defaultmpftest="http://test.com"; (: :)
   //defaultmpftest:defaultmpftest/@test_id'
  passing xmltype.createxml(t.xml_data)
  returning content).getStringVal()
from t_testxml t;

XMLQUERY('DECLARENAMESPACEDEFAULTMPFTEST="HTTP://TEST.COM";(::)//DEFAULTMPFTEST:DEFAULTMPFTEST/@TEST_ID'PASSINGXMLTYPE.CREATEXML(T.XML_DATA)RETURNINGCONTENT).GETSTRINGVAL()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1231

您需要两个 XMLQuery 子句来获取这两个值。我通常会使用 XMLTable 代替,此处显示了通过 CTE 提供的(固定的)XML-as-string:

with t_testxml(xml_data) as (select '<?xml version="1.0" encoding="UTF-8"?>
<defaultmpftest:defaultmpftest xmlns:defaultmpftest="http://test.com"
 test_id="1231"
 test_name="name_test">
<mpftestdata:additionalLinkUrl xmlns:mpftestdata="http://test2.com"/>
</defaultmpftest:defaultmpftest>' from dual
)
select x.test_id, x.test_name
from t_testxml t
cross join xmltable(
  xmlnamespaces('http://test.com' as "defaultmpftest"),
  '//defaultmpftest:defaultmpftest'
  passing xmltype(t.xml_data)
  columns test_id number path '@test_id',
    test_name varchar2(30) path '@test_name'
) x;

   TEST_ID TEST_NAME                     
---------- ------------------------------
      1231 name_test                     

Read more about using these functions.