由于在另一个重复模式中重复节点,在 PL/SQL 中提取部分 XMLType
Posted
技术标签:
【中文标题】由于在另一个重复模式中重复节点,在 PL/SQL 中提取部分 XMLType【英文标题】:Extracting part of XMLType in PL/SQL because of repeating node inside another repeating mode 【发布时间】:2013-08-26 13:20:33 【问题描述】:我有一个 XMLType 对象,我想将开放时间提取到表中。
<workspace>
<title>workspace1</title>
<item>
<day>1</day>
<openingTime>8:00</openingTime>
<closingTime>12:00</closingTime>
</item>
<item>
<day>1</day>
<openingTime>13:00</openingTime>
<closingTime>18:00</closingTime>
</item>
<workspace>
<workspace>
<title>workspace2</title>
<item>
<day>1</day>
<openingTime>9:00</openingTime>
<closingTime>14:00</closingTime>
</item>
<item>
<day>3</day>
<openingTime>12:00</openingTime>
<closingTime>16:00</closingTime>
</item>
<workspace>
我会使用类似的东西:
SELECT ExtractValue(Value(p),'workspace/item/day/text()') as day
,ExtractValue(Value(p),'workspace/item/openingTime/text()') as open
,ExtractValue(Value(p),'workspace/item/closingTime/text()') as close
FROM TABLE (XMLSequence(Extract(y,'workspace'))) p
WHERE ExtractValue(Value(p),'/workspace/title/text()') LIKE 'workspace1';
其中 y 是上面的 XMLType。但这不起作用,因为它仍然会找到多个 item 节点。我需要提取标题工作区 2 的所有元素值(值 1、9:00、14:00、3、12:00、16:00)。如果我不仅可以提取值,而且可以提取 XMLType 的整个部分,那将会有所帮助。有任何想法吗? 谢谢,迈克尔
【问题讨论】:
【参考方案1】:您的目标可以通过使用XMLTable 来实现:
with x as ( -- Just to introduce XML parameter
select
xmltype('
<workspace_list>
<workspace>
<title>workspace1</title>
<item>
<day>1</day>
<openingTime>8:00</openingTime>
<closingTime>12:00</closingTime>
</item>
<item>
<day>1</day>
<openingTime>13:00</openingTime>
<closingTime>18:00</closingTime>
</item>
</workspace>
<workspace>
<title>workspace2</title>
<item>
<day>1</day>
<openingTime>9:00</openingTime>
<closingTime>14:00</closingTime>
</item>
<item>
<day>3</day>
<openingTime>12:00</openingTime>
<closingTime>16:00</closingTime>
</item>
</workspace>
</workspace_list>
') xfield
from dual
)
select
workspace, day, opening_time, closing_time
from
XMLTable(
'
for $i in $doc//workspace[title eq $workspace_filter]
for $j in $i/item
return
<wks_item>
<wks_name>$i/title/text()</wks_name>
$j/*
</wks_item>
'
passing
(select xfield from x) as "doc",
('workspace1') as "workspace_filter"
columns
workspace varchar2(100) path '//wks_name',
day varchar2(100) path '//day',
opening_time varchar2(100) path '//openingTime',
closing_time varchar2(100) path '//closingTime'
)
SQLFiddle Example
请注意,我引入了 <workspace_list>
顶部元素并添加了斜线以关闭 <workspace>
元素以使 XML 有效。
【讨论】:
【参考方案2】:使用一些@ThinkJet 技巧,您的查询可能看起来像这样
with x as (
select
xmltype('
<workplaces>
<workspace>
<title>workspace1</title>
<item>
<day>1</day>
<openingTime>8:00</openingTime>
<closingTime>12:00</closingTime>
</item>
<item>
<day>1</day>
<openingTime>13:00</openingTime>
<closingTime>18:00</closingTime>
</item>
</workspace>
<workspace>
<title>workspace2</title>
<item>
<day>1</day>
<openingTime>9:00</openingTime>
<closingTime>14:00</closingTime>
</item>
<item>
<day>3</day>
<openingTime>12:00</openingTime>
<closingTime>16:00</closingTime>
</item>
</workspace>
</workplaces>
') xfield
from dual
)
SELECT "day", "openingTime", "closingTime"
FROM xmltable('$doc//workspace[title=$workspace_filter]/item'
passing (select xfield from x) as "doc",
('workspace1') as "workspace_filter"
columns "openingTime" path '//openingTime',
"closingTime" path '//closingTime',
"day" path '//day')
【讨论】:
我在你的和@ThinkJet 解决方案之间使用了一些东西,但这需要相当长的时间(大约 6 分钟)。但我正在通过 Web 服务读取相当大的 XML 文件(cca 8 MB),所以也许这不是解决方案的错误 仔细想想,一点也不慢,8MB 6 分钟快得要死以上是关于由于在另一个重复模式中重复节点,在 PL/SQL 中提取部分 XMLType的主要内容,如果未能解决你的问题,请参考以下文章