使用 PL SQL 读取 XML 元素的出现
Posted
技术标签:
【中文标题】使用 PL SQL 读取 XML 元素的出现【英文标题】:Reading XML element occurrences using PL SQL 【发布时间】:2015-02-25 12:06:03 【问题描述】:我有这个 XML。
<a>
<b>b1</b>
<c>c1</c>
<b>b2</b>
<c>c2</c2>
</a>
我希望能够使用 PL\SQL 提取元素“b”和“c”的值。我正在使用 Oracle 10g。
到目前为止,我有这个,
SELECT XML.b
, XML.c
FROM XMLTable (
'/a' PASSING p_xml
COLUMNS
b VARCHAR(2) PATH 'b/.'
, c VARCHAR(2) PATH 'c/.'
) XML
但我不断收到此错误:
19279. 00000 - "XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence"
*Cause: The XQuery sequence passed in had more than one item.
*Action: Correct the XQuery expression to return a single item sequence.
然后我尝试了这个:
SELECT XML.b
, XML1.c
FROM XMLTable (
'/a/b' PASSING p_xml
COLUMNS
b VARCHAR(2) PATH '.'
) XML,
XMLTable (
'/a/c' PASSING p_xml
COLUMNS
c VARCHAR(2) PATH '.'
) XML1
但结果是:
b1,c1
b1,c2
b2,c1
b2,c2
当我只想: b1 c1 b2 c2
你们能帮帮我吗?
【问题讨论】:
【参考方案1】:我没有运行它,但据我所知,下面的代码应该可以工作;
DECLARE
vs_Xml VARCHAR2(32000):= '<INPUT>
<A>
<B>1</B>
</A>
<A>
<B>2</B>
</A>
</INPUT>';
vx_ParameterList XMLTYPE;
vx_Parameter XMLTYPE;
vn_ParameterIndex NUMBER;
vs_Key VARCHAR2(64);
vs_XPath VARCHAR2(255);
vs_Value VARCHAR2(10000);
BEGIN
vx_ParameterList := xmltype(vs_Xml);
vn_ParameterIndex := 1;
vs_XPath := '/INPUT/A';
WHILE vx_ParameterList.existsNode(vs_XPath || '[' || vn_ParameterIndex || ']') = 1 LOOP
vx_Parameter := vx_ParameterList.extract(vs_XPath || '[' || vn_ParameterIndex || ']');
vs_Value := vx_Parameter.extract('//B/text()').GetStringVal();
vn_ParameterIndex := vn_ParameterIndex + 1;
dbms_output.put_line(vs_Value);
END
【讨论】:
【参考方案2】:您必须在XMLTABLE
命令中调整xquery 表达式。基本思想是产生一个 xml 记录流,每条记录都可以映射到数据库记录的列。
原始xml中的障碍是xpath轴/a
返回-措辞草率-所有 xml记录的内容。
解决方案是在 /a
上构建一个迭代器,以逐个传递 xml 记录(技术上:包装在合成的 x
元素中)。
以下可以从sqlplus发出:
SELECT myxml.b
, myxml.c
FROM XMLTable (
'for $i in (1, let $x := fn:count(/a/b) return $x )
let $b := /a/b[$i], $c := /a/c[$i]
return <x>
<b>$b</b>
<c>$c</c>
</x>
' PASSING XMLTYPE(
'<a>
<b>b1</b>
<c>c1</c>
<b>b2</b>
<c>c2</c>
</a>')
COLUMNS
b VARCHAR(2) PATH '/x/b'
, c VARCHAR(2) PATH '/x/c'
) myxml
;
更新
为了允许任意数量的b
/c
孩子,下面这行
for $i in (1, let $x := fn:count(/a/b) return $x )
替换原来的
for $i in (1, 2)
在上面的表达式中。
参考
有关 XQuery 语法的更多信息可以在W3c spec 中找到(深度链接到所谓的 FWLOR 表达式的语法文档)。
【讨论】:
以上是关于使用 PL SQL 读取 XML 元素的出现的主要内容,如果未能解决你的问题,请参考以下文章
通过 PL SQL 读取 XML(存储在 Long 变量中)
读取 XML 格式的字符串并使用 PL SQL 中的 for 循环进行更新