我正在学习如何在Oracle 11g中使用XMLQuery和XMLtable功能,而我在使用XMLTable查询时尝试在XPath中使用变量而不是特定字符串。 例如:
echo Please enter admin credentials (This will be stored in a secure string:
powershell -Command "& { read-host -assecurestring | convertfrom- securestring | out-file C:\S3BS\reports\input.txt; } "
我使用此查询来解析XML。但在某些情况下,XML是不同的,我有一个新的XPath。我试图将XPath放在这样的变量中:
DECLARE
px_return XMLTYPE
:= XMLTYPE (
'<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Header xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
</SOAP:Header>
<SOAP:Body xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<n0:validatePolicyCancelResponse xmlns:n0="urn:enterprise.com/ws/SAP/Finantial/MaintainMandate/V1">
<return>
<messageType>E</messageType>
</return>
</n0:validatePolicyCancelResponse>
</SOAP:Body>
</soap:Envelope>');
lv_msgType VARCHAR2 (20);
lv_urlString VARCHAR2 (40);
BEGIN
SELECT Return.msgType
INTO lv_msgType
FROM XMLTABLE (
xmlnamespaces (
DEFAULT 'enterprise.com/ws/SAP/Finantial/MaintainMandate/V1',
'http://schemas.xmlsoap.org/soap/envelope/' AS "soap",
'http://schemas.xmlsoap.org/soap/envelope/' AS "SOAP",
'enterprise.com/ws/SAP/Finantial/MaintainMandate/V1' AS "n0"),
'//soap:Envelope/SOAP:Body/n0:validatePolicyCancelResponse/return'
PASSING px_return
COLUMNS msgType VARCHAR2 (1) PATH 'messageType') Return;
DBMS_OUTPUT.put_line ('Message type: ' || lv_msgType);
END;
并在XMLTable查询中替换为:
lv_urlString :=
'//soap:Envelope/SOAP:Body/n0:validatePolicyCancelResponse/return';
我收到错误:
SELECT Return.msgType
INTO lv_msgType
FROM XMLTABLE (
xmlnamespaces (
DEFAULT 'enterprise.com/ws/SAP/Finantial/MaintainMandate/V1',
'http://schemas.xmlsoap.org/soap/envelope/' AS "soap",
'http://schemas.xmlsoap.org/soap/envelope/' AS "SOAP",
'enterprise.com/ws/SAP/Finantial/MaintainMandate/V1' AS "n0"),
lv_urlString
PASSING px_return
COLUMNS msgType VARCHAR2 (1) PATH 'messageType') Return;
任何人都可以通过重复使用相同的查询,但应用不同的路径来帮助我这样做吗?
答案 0 :(得分:2)
我遇到了同样的问题(11.2.0.3.0和12.1.0.2.0)。当查询字符串引用命名空间时,您似乎无法在xmltable处使用PL / SQL变量代替 XQuery_string 。请注意,如果您没有引用命名空间,则可以使用PL / SQL变量(参见下面的示例#3)。
引发的异常description:
LPX-01081:[XPST0081]前缀无效
原因:如果查询中使用的QName包含无法通过使用静态已知名称空间扩展到名称空间URI的名称空间前缀,则会出现静态错误。
行动:无
如果使用变量而不是字符串文字的事实似乎被Oracle弃用了。 Oracle支持文档Doc ID 1490150.1(仅适用于付费客户)表明存在补丁(案例与我们的案例不完全相同但非常相似)但文档还指出:
因此Oracle建议仅使用字符串文字。
我最初的困惑是由Oracle自己的文档(11.2)中的以下冲突引起的:
XMLTABLE SQL/XML Function in Oracle XML DB中的XMLTABLE中的
XQuery_string
是一个完整的XQuery表达式,可能包含一个prolog,作为文字字符串。
Database SQL Language Reference:
XQuery_string
是一个完整的XQuery表达式,可以包含prolog声明。
请注意缺少的&#34;作为字符串文字&#34; 来自第二个引号。当然,我首先只阅读数据库SQL语言参考 ...
XMLTABLE文档已在12.1 version中修复:
XQuery_string
是一个文字字符串。它是一个完整的XQuery表达式,可以包含prolog声明。
所以答案是不要将变量用作 XQuery_string ,即使它编译,在某些情况下似乎也能正常工作。
在下面您将找到重现问题的最小示例:
示例#1
这适用于打印&#39;这是A。&#39;如预期的那样。
declare
v_xml constant xmltype := xmltype('
<ns:a
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns="http://stackoverflow.com/users/272735/a">
<foo><bar>This is A.</bar></foo>
</ns:a>
');
v_content varchar2(100);
begin
select bar into v_content
from xmltable(
xmlnamespaces('http://stackoverflow.com/users/272735/a' as "ns")
,'/ns:a/foo' passing v_xml
columns
bar varchar2(4000) path 'bar'
);
dbms_output.put_line(v_content);
end;
/
示例#2
这失败了:
ORA-19112: error raised during evaluation:
XVM-01081: [XPST0081] Invalid prefix
1 /ns:a/foo
- ^
declare
v_xml constant xmltype := xmltype('
<ns:a
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns="http://stackoverflow.com/users/272735/a">
<foo><bar>This is A.</bar></foo>
</ns:a>
');
v_xquery_string constant varchar2(100) := '/ns:a/foo';
v_content varchar2(100);
begin
select bar into v_content
from xmltable(
xmlnamespaces('http://stackoverflow.com/users/272735/a' as "ns")
,v_xquery_string passing v_xml
columns
bar varchar2(4000) path 'bar'
);
dbms_output.put_line(v_content);
end;
/
示例#3
这适用于打印&#39;这是A。&#39;如预期的那样。
declare
v_xml constant xmltype := xmltype('<a><foo><bar>This is A.</bar></foo></a>');
v_xquery_string constant varchar2(100) := '/a/foo';
v_content varchar2(100);
begin
select bar into v_content
from xmltable(
v_xquery_string passing v_xml
columns
bar varchar2(4000) path 'bar'
);
dbms_output.put_line(v_content);
end;
/
答案 1 :(得分:1)
似乎您在XML中使用了错误的XML名称空间前缀
使用的前缀是soap
,但名称空间声明是
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/
尝试将其更改为肥皂
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/
但这并不能解释所描述的问题