我需要从包含完整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元素名称空间的任何其他方法?
答案 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>