I am trying to get the count of nodes in an XML field. but I always see 0 as the result. Here is how my query looks like.
DECLARE @XmlTable TABLE (XmlResult XML)
INSERT INTO @XmlTable EXECUTE [dbo].usp_GetBooks @EditionId=400
--select * from @XmlTable
SELECT
--Count number of nodes
COUNT(*) AS BooksCount
FROM
(
SELECT XmlResult FROM @XmlTable
) AS XmlTable(XmlColumn)
CROSS APPLY XmlColumn.nodes('./books/book') XmlTableFunction(XmlColumn2);
My XML Looks like :
<Version number ="1">
<books>
<book>
<name> </name>
<author></author>
</book>
<book>
<name> </name>
<author></author>
</book>
</books>
</Version>
Count the XML elements (XPath) newInstance(). newXPath(); NodeList nodes = (NodeList) xpath. evaluate("//staff", doc, XPathConstants. NODESET); int count = nodes.
Querying in an XQuery contextIf your query invokes an XQuery expression directly, you must prefix it with the case-insensitive keyword XQUERY. To retrieve all of the XML documents previously inserted into the INFO column, you can use XQuery with either db2-fn:xmlcolumn or db2-fn:sqlquery.
You can retrieve multiple values from the rowset. For example, you can apply the value() method to the rowset returned by nodes() and retrieve multiple values from the original XML instance. The value() method, when applied to the XML instance, returns only one value.
You can optionally retrieve formal results of a SQL query as XML by specifying the FOR XML clause in the query. The FOR XML clause can be used in top-level queries and in subqueries. The top-level FOR XML clause can be used only in the SELECT statement.
I think your XPath expression is wrong - try this instead:
DECLARE @XmlTable TABLE (XmlResult XML)
INSERT INTO @XmlTable EXECUTE [dbo].usp_GetBooks @EditionId=400
SELECT
COUNT(*) AS BooksCount
FROM
(SELECT XmlResult FROM @XmlTable) AS XmlTable(XmlColumn)
CROSS APPLY
XmlColumn.nodes('/Version/books/book') XmlTableFunction(XmlColumn2)
Or even simpler:
DECLARE @XmlTable TABLE (XmlResult XML)
INSERT INTO @XmlTable EXECUTE [dbo].usp_GetBooks @EditionId=400
SELECT
XmlResult.value('count(/Version/books/book)', 'int')
FROM
@XmlTable
Works for me with the XML pattern you give
DECLARE @XmlTable TABLE (XmlResult XML)
INSERT INTO @XmlTable VALUES ('<books><book><title>GWTW</title></book></books>')
INSERT INTO @XmlTable VALUES ('<foo />')
INSERT INTO @XmlTable VALUES ('<books />')
SELECT
COUNT(*) AS BooksCount
FROM
(
SELECT XmlResult FROM @XmlTable
) AS XmlTable(XmlColumn)
CROSS APPLY XmlColumn.nodes('./books/book') XmlTableFunction(XmlColumn2);
Exist method is quite useful too. I use NULLIF to change 0 to NULL (it is bit so would need CAST with SUM)
SELECT COUNT(NULLIF(XmlResult.exist('./books/book'), 0)) FROM @XmlTable
Edit, after update
The XML you posted is wrong too.
You are not specifying the root note correctly:
DECLARE @XmlTable TABLE (XmlResult XML)
INSERT INTO @XmlTable VALUES ('
<Version number ="1">
<books>
<book>
<name> </name>
<author></author>
</book>
<book>
<name> </name>
<author></author>
</book>
</books>
</Version>')
SELECT
COUNT(*)
FROM
(
SELECT XmlResult FROM @XmlTable
) AS XmlTable(XmlColumn)
CROSS APPLY XmlColumn.nodes('/Version/books/book') XmlTableFunction(XmlColumn2);
SELECT
COUNT(*)
FROM
(
SELECT XmlResult FROM @XmlTable
) AS XmlTable(XmlColumn)
CROSS APPLY XmlColumn.nodes('*/books/book') XmlTableFunction(XmlColumn2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With