Getting Started with Adobe After Effects - Part 6: Motion Blur


Upload Image Close it
Select File

My technology blog on SQL Server, TSQL, XML, FILESTREAM and other areas of SQL Server.
Browse by Tags · View All
XML 112
TSQL 69
XQuery 69
XQuery Functions 67
XQuery Training 65
XQuery in TSQL 64
XQuery Tutorial 63
SQL Server XQuery 63
XQuery-Labs 57
BRH 38

Archive · View All
September 2008 32
August 2008 30
July 2008 21
August 2009 19
June 2009 19
May 2010 18
January 2009 15
January 2010 14
October 2008 14
June 2008 13

XQuery Lab 61 – Writing a Recursive CTE to process an XML document

Jun 29 2010 7:02PM by Jacob Sebastian   

We have seen several examples of writing recursive queries in the earlier blog posts. For a quick recap, you can find some of those posts in the list given below.

  1. TSQL Lab 10 - Performing recursive updates in SQL Server
  2. TSQL Lab 11 - Writing a recursive procedure to update the count of child items under each parent category
  3. TSQL Lab 12 - Writing a recursive procedure to handle more than 32 levels
  4. TSQL Lab 14 - Performing a recursive update for more than 32 levels
  5. TSQL Lab 18 - Performing Recursive Updates using CTE
  6. TSQL Lab 20 - Performing recursive updates using a BOTTOM to TOP recursive CTE
  7. Recursive CTE and Ordering of the hierarchical result

In this XQuery Lab, we will see how to write a recursive CTE to process all the elements and attributes of an XML Document. In XQuery Lab 39, we saw an example that generated the fully qualified path to all the elements and attributes of an XML document using OPENXML(). In this lab, let us look at a new version of the same code using XQuery (instead of OPENXML).

This code is a stripped down version of XQuery Lab 58 which presented a generic function to query the content of an XML document.

DECLARE @x XML  
SELECT @x = '
<books>
    <book id="101">
        <title>my book</title>
        <author>Myself</author>
    </book>
    <book id="202">
        <title>your book</title>
        <author>you</author>
    </book>
</books>'

;WITH cte AS ( 
    SELECT 
        1 AS lvl, 
        x.value('local-name(.)','VARCHAR(MAX)') AS FullPath, 
        x.value('text()[1]','VARCHAR(MAX)') AS Value, 
        x.query('.') AS CurrentNode,        
        CAST(CAST(1 AS VARBINARY(4)) AS VARBINARY(MAX)) AS Sort
    FROM @x.nodes('/*') a(x) 
    UNION ALL 
    SELECT 
        p.lvl + 1 AS lvl, 
        CAST( 
            p.FullPath 
            + '/' 
            + c.value('local-name(.)','VARCHAR(MAX)') AS VARCHAR(MAX) 
        ) AS FullPath, 
        CAST( c.value('text()[1]','VARCHAR(MAX)') AS VARCHAR(MAX) ) AS Value, 
        c.query('.')  AS CurrentNode,        
        CAST( 
            p.Sort 
            + CAST( (lvl + 1) * 1024 
            + (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) * 2) AS VARBINARY(4) 
        ) AS VARBINARY(MAX) ) AS Sort
    FROM cte p 
    CROSS APPLY CurrentNode.nodes('/*/*') b(c)        
), cte2 AS (
	SELECT 
		FullPath, 
		Value, 
		Sort 
	FROM cte 
	UNION ALL 
	SELECT 
		p.FullPath + '/@' + x.value('local-name(.)','VARCHAR(MAX)'), 
		x.value('.','VARCHAR(MAX)'),
		Sort 
	FROM cte p 
	CROSS APPLY CurrentNode.nodes('/*/@*') a(x) 
)
SELECT FullPath, value 
FROM cte2
WHERE Value IS NOT NULL
ORDER BY Sort 
/*
FullPath             Value
-------------------- ------------------------------
books\book\@id       101
books\book\title     my book
books\book\author    Myself
books\book\@id       202
books\book\title     your book
books\book\author    you
*/

Tags: XML, XQuery, BRH, XQuery Functions, xquery labs, #XML, #XQUERY, SQL Server - XQuery, SQL Server XQuery, XQuery in TSQL, XQuery Training, XQuery Tutorial,


Jacob Sebastian
1 · 100% · 32004
1
 
0
Lifesaver
 
0
Refreshed
 
0
Learned
 
0
Incorrect



Submit

11  Comments  

  • Hi Jacob,

    Here is another approach to get same result. This approach uses the edge table from OPENXML function.

    USE tempdb; GO CREATE TABLE #T ( id bigint NOT NULL PRIMARY KEY, parentid bigint NULL, nodetype int NOT NULL, -- 1 - element, 2 - attribute, 3 - text localname nvarchar(max) NULL, --prefix nvarchar(max) NULL, --namespaceuri nvarchar(max) NULL, --datatype nvarchar(128) NULL, --prev bigint NULL, [text] nvarchar(max) ); DECLARE @idoc int DECLARE @x XML

    SET @x = ' my book Myself your book you The Art of XSD A good friend ';

    EXEC spxmlpreparedocument @idoc OUTPUT, @x;

    INSERT INTO #T ( id, parentid, nodetype, localname, -- prefix, -- namespaceuri, -- datatype, -- prev, [text] ) SELECT id, parentid, nodetype, localname, -- prefix, -- namespaceuri, -- datatype, -- prev, [text] FROM OPENXML(@idoc, '.') AS T;

    EXEC spxmlremovedocument @idoc;

    WITH rs AS ( SELECT id, parentid, nodetype, localname AS FullPath, [text] AS [Value], CAST(id AS varbinary(64)) AS sort FROM #T WHERE parentid IS NULL

    UNION ALL

    SELECT C.id, C.parentid, C.nodetype, P.FullPath + CASE C.nodetype WHEN 1 THEN '/' WHEN 2 THEN '@' ELSE '' END + CASE WHEN C.nodetype = 3 THEN '' ELSE C.localname END, C.[text] AS [Value], CAST(P.sort + CAST(C.id AS binary(4)) AS varbinary(64)) FROM rs AS P INNER JOIN #T AS C ON P.id = C.parentid ) SELECT FullPath, [Value] FROM rs WHERE nodetype = 3 ORDER BY sort; GO DROP TABLE #T; GO

    Cheers, AMB

    commented on Aug 12 2010 1:46PM
    Alejandro Mesa
    266 · 1% · 164
  • Agreed with you. I had presented another example that is very close to this in one of the earlier labs. http://beyondrelational.com/blogs/jacob/archive/2009/01/23/xquery-lab-39-retrieve-fully-qualified-path-of-attributes-and-elements.aspx

    I agree with you that the node table generated by OPENXML() is really good.

    commented on Aug 12 2010 1:55PM
    Jacob Sebastian
    1 · 100% · 32004
  • Thanks for providing this solution. When I extract the contents of our XML column into a text file and then copy it as the assignment to @x, it works great. When I replace @x with "mytablename.mycolumnname" in the first FROM statement and remove the original @x assignment prior to ";WITH cte AS ( ", I get an error message: "Error: The object name 'dbo.mytablename.mycolumnname.nodes' contains more than the maximum number of prefixes. The maximum is 3. Might this have something to do with the namespace in the XML column? Thanks, Dave

    commented on Sep 1 2010 5:40PM
    DCN1034
    1557 · 0% · 12
  • can you post a repro script that I can examine?

    commented on Oct 16 2010 3:38PM
    JacobSebastian
    47 · 4% · 1215
  • I'm trying to get your Lab 61 example to work for an XML column within a SQL Server database table instead of using the @x assignment so that I can read through many rows within the database table. Should this example be able to work with a namespace? All of my typical XQuery efforts start off with a namespace expression.

    Here is an example of one of my XQuery scripts that uses an XML database column to read through multiple XML documents within the database table; for example:

    Relevant snippet of the XSD that defines the structure of xml column XML_COLUMN:

    <Coverage>
        <CoverageCd>
        <CategoryCd>
    </Coverage>
    
    WITH XMLNAMESPACES('http://www.mycompany.com/ACORD1.11.0/Policy_1.0/xml' AS "ns")
    select non_xml_column,
               CovCd.i.value('.', 'varchar(80)')   as CoverageCd,
               CatCd.i.value('.', 'varchar(80)')    as CategoryCd
    
    from    dbo.my_table
                cross apply XML_COLUMN.nodes('.//ns:Coverage') as Cov(i)
                outer apply Cov.i.nodes('ns:CoverageCd') as CovCd(i)
                outer apply Cov.i.nodes('ns:CategoryCd') as CatCd(i)
    
    where  non_xml_column = "some condition"
    

    Any help would be appreciated.

    commented on Aug 5 2011 12:36PM
    DCN1034
    1557 · 0% · 12
  • It doesn't appear that the XSD snippet showed up in my last post, the relevant XPaths from the XSD would look like this:

    /Coverage/CoverageCd,
    /Coverage/CategoryCd

    commented on Aug 5 2011 12:46PM
    DCN1034
    1557 · 0% · 12
  • The XML sample you posted (line 1 to 4) does not show the existence of namespace declarations. There fore, I do not understand the reason for using WITH XMLNAMESPACES in your query.

    Is the XML presented above complete? Can you post another XML sample with some data and show me the expected output? Also, when posting make sure that you format the code using the 'sample code' formatting option provided in the toolbar.

    commented on Aug 7 2011 10:03PM
    Jacob Sebastian
    1 · 100% · 32004
  • Sorry, the XML provided is not complete and probably not the best example. The XML tags I showed earlier in lines 1 to 4 are prefixed with "ns:".

    I am working with a database table column of type xml that can hold an XML document. The XSD associated with this XML document is based on the ACORD Property & Casualty schema, which is extended with our company-specific nodes.

    I am able to make use of your query example "XQuery Lab 61 – Writing a Recursive CTE to process an XML document", by substituting a text version of one of my XML documents as the assignment to "@x". The query output produced is in the same format as the one you are showing in the XQuery Lab 61 example ... all of the XPaths and associated data values from my XML document.

    However, I need to read from my database table and using the column values, instead of using an "@x" assignment, and produce this same output for multiple XML documents. I've tried incorporating your Lab # 61 code within my typical XQuery example presented earlier (lines 6 to 16) without success.

    So basically I'm wondering, can the Lab # 61 query be adapted to take input from a database table column instead of an assignmemt to "@x"?

    Thanks again in advance for your assistance. Dave

    commented on Aug 8 2011 8:53AM
    DCN1034
    1557 · 0% · 12
  • I see your point. When you process an XML variable, you are dealing with only one XML document at a time. When you deal with an XML column, you might want to process more than one row at a time. So the code needed to deal with XML columns is slightly different.

    Here is how we typically read information from an XML variable.

    SELECT
       x.value('expression here')
    FROM @x.nodes('path here') a(x)
    

    If the same has to performed from an XML column, the code will look as follows:

    SELECT
       x.value('expression here')
    FROM tablename 
    CROSS APPLY XMLColumnName.nodes ('path here') a(x)
    

    hope this helps.

    commented on Aug 8 2011 8:57PM
    Jacob Sebastian
    1 · 100% · 32004
  • Jacob,

    Thanks for pointing me in the right direction. I was able to incorporate my xml column into your XQuery example and now have this working for multiple XML documents.

    This will be a tremendous help.

    Dave

    commented on Aug 9 2011 8:01AM
    DCN1034
    1557 · 0% · 12
  • Dave, I am glad to know that my post was helpful.

    commented on Aug 10 2011 4:39AM
    Jacob Sebastian
    1 · 100% · 32004

Your Comment


Sign Up or Login to post a comment.

"XQuery Lab 61 – Writing a Recursive CTE to process an XML document" rated 5 out of 5 by 1 readers
XQuery Lab 61 – Writing a Recursive CTE to process an XML document , 5.0 out of 5 based on 1 ratings
    Copyright © Rivera Informatic Private Ltd Contact us      Privacy Policy      Terms of use      Report Abuse      Advertising      [ZULU1097]