如何在Oracle中使用命名空间查询XML?

时间:2016-07-18 14:42:06

标签: xml xpath plsql namespaces xquery

我需要从包含完整XML文档的XMLType变量中提取PLSQL过程中的数据,具有以下结构(简化如下):

<?xml version="1.0" encoding="utf-8"?>
<AA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://my.domain/cat1/">
  <Element>
    <ID>2</ID>
    <Value>46544</Value>
  <Element>
</AA>

我正在使用XMLTable函数,但是使用简单的/AA/Element XPath表达式却没有数据:

SELECT C1, C2
INTO v_id, v_val
FROM XMLTable('/AA/Element'
                   passing v_MyXML columns
                    C1 number path 'ID',
                    C2 number path 'Value'
                )

以下任何一种表达方式都没有:

'/*.AA/Element'
'declare default element namespace "http://my.domain/cat1/"; /AA/Element'
'declare namespace xsi="http://www.w3.org/2001/XMLSchema-instance"; declare namespace xsd="http://www.w3.org/2001/XMLSchema"; declare default element namespace "http://jpk.mf.gov.pl/wzor/2016/03/09/03094/"; /AA/Element'

我能够提取数据的唯一方法是修改文档/变量并简单地替换

<AA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://my.domain/cat1/">

<AA>

这不是完美的解决方案,因为我需要修改文档并使用适当的属性返回它的初始结构。 任何人都可以建议如何修改XPath表达式以获取数据吗? 或者可以使用忽略AA元素名称空间的任何其他方法?

2 个答案:

答案 0 :(得分:1)

/*.AA/Element

您需要使用冒号:而不是点.来分隔命名空间和元素名称。此外,在这种情况下,命名空间将继承到<Element/>子节点,因此正确的查询将是

/*:AA/*:Element

声明默认元素命名空间的查询应该可以正常工作。我找不到Oracle不支持的跟踪。

declare default element namespace "http://my.domain/cat1/";
/AA/Element

在上一个示例中,您定义了其他名称空间。

declare namespace xsi="http://www.w3.org/2001/XMLSchema-instance";
declare namespace xsd="http://www.w3.org/2001/XMLSchema";
declare default element namespace "http://jpk.mf.gov.pl/wzor/2016/03/09/03094/";
/AA/Element

我猜my.domain命名空间实际上就是这个。最后,这与示例2中的查询相同:其他两个名称空间前缀更新。如果通配符命名空间仍然无效,请尝试使用前缀注册命名空间(选择适当的前缀,您可以自己定义):

declare namespace cat1="http://my.domain/cat1/";
/cat1:AA/cat1:Element

答案 1 :(得分:1)

@JensErat已经提供了XML背景,所以我不必这样做。相反,您可以在下面找到一个工作示例,了解如何在Oracle PL / SQL中应用所有这些。

您需要使用xmltable XML命名空间子句

  

XMLNAMESPACES子句包含一组XML名称空间声明。这些声明由XQuery表达式(计算的XQuery_string)引用,该表达式计算行,并通过XML_table_column的PATH子句中的XPath表达式引用,该表达式计算整个XMLTable函数的列。如果要在COLUMNS子句的PATH表达式中使用限定名称,则需要指定XMLNAMESPACES子句。

您还可以使用默认 XML命名空间子句:

xmlnamespaces(default 'http://my.domain/cat1/')

然后你不必使用命名空间前缀。

没有默认命名空间的示例

declare
  v_xml constant xmltype := xmltype('<AA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://my.domain/cat1/">
  <Element>
    <ID>2</ID>
    <Value>46544</Value>
  </Element>
</AA>'
);
 v_id number;
 v_value number;
begin
  select   id,   value_
    into v_id, v_value
  from xmltable(
    xmlnamespaces('http://my.domain/cat1/' as "foo"),
    '/foo:AA/foo:Element' passing v_xml
    columns
    id number path 'foo:ID',
    value_ number path 'foo:Value'
  );

  dbms_output.put_line('(v_id = ' || v_id || ')(v_value = ' || v_value || ')');
end;
/

默认命名空间的示例

declare
  v_xml constant xmltype := xmltype('<AA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://my.domain/cat1/">
  <Element>
    <ID>2</ID>
    <Value>46544</Value>
  </Element>
</AA>'
);
 v_id number;
 v_value number;
begin
  select   id,   value_
    into v_id, v_value
  from xmltable(
    xmlnamespaces(default 'http://my.domain/cat1/'),
    '/AA/Element' passing v_xml
    columns
    id number path 'ID',
    value_ number path 'Value'
  );

  dbms_output.put_line('(v_id = ' || v_id || ')(v_value = ' || v_value || ')');
end;
/

示例运行:

SQL> @so58
(v_id = 2)(v_value = 46544)

PL/SQL procedure successfully completed.

SQL>