I have a table having one columns as XMLTYPE being stored with Object-Relational storage. Below is table ddl.
CREATE TABLE Orders ( Order_id number not null,
Order_status Varchar2(100),
Order_desc XMLType not null )
XMLTYPE Order_desc STORE AS OBJECT RELATIONAL
XMLSCHEMA "http://localhost/public/xsd/Orderstore.xsd"
ELEMENT "OrderVal";
I have successfully registered the schema to load XSD with XML DB. Below is the XML being loaded into the XMLTYPE column.
<?xml version="1.0" encoding="utf-8" ?>
<draftorders>
<OrderSumm>
<Ordercod>OrderBookings</Ordercod>
</OrderSumm>
<Orderattrs>
<Orderattr Ordername="HROrder">
<OrderVals>
<OrderVal>
<listvalue>Order1</listvalue>
<Orderattrs>
<Orderattr Ordername="Node1_Child1">
<OrderVals>
<OrderVal>
<listvalue><![CDATA[ Node1_Child1_OrderValue_1]]></listvalue>
<Orderattrs>
<Orderattr Ordername="Node2_Child1">
<OrderVals>
<OrderVal>
<listvalue><![CDATA[ Node2_Child1_OrderValue_1]]></listvalue>
</OrderVal>
</OrderVals>
</Orderattr>
<Orderattr Ordername="Node2_Child2">
<OrderVals>
<OrderVal>
<listvalue><![CDATA[ Node2_Child2_OrderValue_1]]></listvalue>
</OrderVal>
</OrderVals>
</Orderattr>
</Orderattrs>
</OrderVal>
</OrderVals>
</Orderattr>
</Orderattrs>
</OrderVal>
</OrderVals>
</Orderattr>
</Orderattrs>
</draftorders>
This XML contain around 2500 values for Node2 Orderattr. Am using the below query to print out all the Node2 values in one go using XMLTABLE.
SELECT ord.OrdName, ord.OrdVal
FROM Orders, XMLTable('/OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr'
PASSING Order_desc
COLUMNS "OrdName" VARCHAR2(4000) PATH '@Ordername',
"OrdVal" VARCHAR2(4000) PATH 'OrderVals/OrderVal[1]/listvalue') ord;
Output:-
Node2_Child1
Node2_Child1_OrderValue_1
Node2_Child2
Node2_Child2_OrderValue_1
......
Node2_Child2500
Node2_Child2500_OrderValue_1
Now I want to restrict my resultset to only first 25 Node2 Orderattr values and not the entire set. How should I go about restricting the resultset to only first 25 node values.
Able to get it using XMLTable.
I have tried below XMLQuery function to achieve the same above output, but receive truncated output.
SELECT XMLQuery( '/OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr/(@listname, OrderVals/OrderVal/listvalue/text())'
PASSING o.Order_desc RETURNING CONTENT)
FROM Orders o;
Output:- Node2_Child1Node2_Child1_OrderValue_1Node2_Child2Node2_Child2_OrderValue_1Node2_Child3Node2_Child3_OrderValue_1Node2_Child4Node2_Child4_OrderValue_1Node2_Child5Node2_Child5_OrderValue_1........Node2_Child25Node2_Child25_OrderValue_1
Thanks...
You need to add a condition with position()
Xpath function to the end of a XQuery expression:
...
XMLTable(
'/OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr[position() <= 25]'
...
SQLFiddle test with your exapmle
Update
Question updated, so a little bit more about XMLQuery()
function.
First of all, this function return single XMLType, therefore to get individual elements you need to use ExtractValue()
function:
with params as (
select XMLParse(content '
<draftorders>
<!-- EXAMPLE XML FROM QUESTION GOES HERE -->
</draftorders>
')
doc from dual
)
select
ExtractValue(xml_val, '/Orderattr/@Ordername') order_name,
ExtractValue(xml_val, '/Orderattr/OrderVals/OrderVal[1]/listvalue') list_value
from (
SELECT
XMLQuery(
'//OrderVal[1]/Orderattrs/Orderattr[1]/OrderVals/OrderVal[1]/Orderattrs/Orderattr[position() < 2]'
PASSING doc returning content
) xml_val
from
params
);
SQLFiddle test for XMLQuery variant
Second: if your XQuery return set of nodes then resulting XML not well-formed because there are no single root node.
Last: In your variant with XMLQuery expression returns set of values, not XML. All value sequences in XQuery concatenated without separators, so you got what you got:
Node2_Child1<![CDATA[ Node2_Child1_OrderValue_1]]>Node2_Child2<![CDATA[ Node2_Child2_OrderValue_1]]>
and after evaluation this expression translated to just
Node2_Child1Node2_Child1_OrderValue_1Node2_Child2Node2_Child2_OrderValue_1
Oops... You mistyped @Ordername
and changed it to @listname
at least in question text, so this part returns empty string and if this expression evaluated without changes result would be like
Node2_Child1_OrderValue_1Node2_Child2_OrderValue_1