Question


I have a XMLType object and I want to extract opening times into table.

<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>

I would use something like:

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';

where y is XMLType above. But that won't work, because it will still find more than one item node. I need to extract ALL element values for title workspace2 (values 1, 9:00, 14:00, 3, 12:00, 16:00). It would help if I could extract not only value, but whole part of XMLType. Any ideas?
Thanks, Michal

Was it helpful?

Solution 2

With some @ThinkJet tricks your query may look like this

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')

OTHER TIPS

Your target may be achieved by using 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

Note that I introduced <workspace_list> top element and added slash for closing <workspace> elements to make XML valid.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top