Reputation: 11
I have an XML document like below. I am trying to get key/value pair for all elements and attributes as well. The query I have gets all elements names and element values. However, I would like to get attribute names and attribute values too (preferably in the same query, otherwise in a different query).
XML Document:
<bookstore>
<book category="COOKING">
<title lang="en">Cook Book</title>
<author>Chef Author</author>
<year>2015</year>
<price>310.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Kid Story Book</title>
<author>KJ Banter</author>
<year>2010</year>
<price>229.99</price>
</book>
</bookstore>
SQL Query in Oracle:
WITH tab AS
(SELECT xmltype('
<bookstore>
<book category="COOKING">
<title lang="en">Cook Book</title>
<author>Chef Author</author>
<year>2015</year>
<price>310.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Kid Story Book</title>
<author>KJ Banter</author>
<year>2010</year>
<price>229.99</price>
</book>
</bookstore>
') col
FROM dual
)
SELECT nodepath,nodevalue
FROM tab t,
xmltable('
for $i in $tmp/descendant::*
where $i/text() != ""
return <R><P>{string-join($i/ancestor-or-self::*/name(), "/")}</P><V>{$i/text()}</V></R>'
passing t.col AS "tmp" columns
nodepath varchar2(1000) path '//P',
nodevalue varchar2(1000) path '//V')
Upvotes: 1
Views: 118
Reputation: 38682
Given you want them in document order, descend for each retrieved element and follow its self- and attribute axis. You need to retrieve element and attribute values differently, so apply a typeswitch
:
for $node in /descendant::*/(., @*)
let $value := (
typeswitch ($node)
case element() return $node/text()
case attribute() return data($node)
default return ()
)
where $value
return <R>
<P>{
string-join(($node/name(), $node/ancestor::*/name()), "/")
}</P>
<V>{ $value }</V>
</R>
Also observe I changed the ancestor-or-self
step to an ancestor
step and explicitly return $node
's name, so we don't have to distinguish between elements and attributes again in the ancestor
axis.
Upvotes: 1