查询xml的结构,而不是SQL Server 2005中的数据

问题描述:

我想查询有关XML的元数据,以帮助确定某些XML的结构。我有一个49 MB的XML文件,我只需要知道所有属性和子标签的列表以及关于它们的一些基本信息。我可以从XML本身查询它,还是必须费力地查阅它并查找其中可能存在的每个元素和属性?没有可用的模式定义。查询xml的结构,而不是SQL Server 2005中的数据

鉴于一些随机的XML如下所示:

DECLARE @x xml 
SET @x = 
'<People> 
<Person age="35"> 
    <Name>Pete</Name> 
    <Phone> 
    <Mobile>555-555-1234</Mobile> 
    <Home>555-555-0001</Home> 
    </Phone> 
</Person> 
<Person age="40" height="70 inches"> 
    <Name>Paul</Name> 
    <Phone> 
    <Mobile>555-555-4567</Mobile> 
    </Phone> 
</Person> 
<Person age="24"> 
    <Name>Susan</Name> 
    <Phone> 
    <Home>555-555-2323</Home> 
    </Phone> 
</Person> 
</People>' 

我将如何查询这回像下面这样?我不需要一个记录集(尽管那当然会很好)。为了得到不同的部分,我不得不反复查询。我可能必须先看到首先有一个root People标记,然后查询People并查看Person标记,然后才能看到该标记下的Name和Phone标记,依此类推。

People maxcount=1 
People.Person maxcount=3 [age maxlen=2 maxcount=3] [weight maxlen=9 maxcount=1] 
Person.Name textnode maxcount=1 maxlen=5 
Person.Name.Phone maxcount=1 
Person.Name.Mobile textnode maxcount=1 maxlen=12 
Person.Name.Home textnode maxcount=1 maxlen=12 
+0

你为什么要使用SQL Server来做到这一点? – 2011-02-03 00:41:29

这种类型的分析可能是通过结构化程序代码最好的。仅仅因为xml可能在数据库中并不意味着xml的分析必须在那里完成。

提取结构是可行的(如下面的查询所示),但像John说的那样...为什么?如果它强制执行约束,则使用xsd,然后将其读入到您的应用程序中。

declare @data xml 

set @data = ' 
<People> 
<Person age="35"> 
    <Name>Pete</Name> 
    <Phone> 
    <Mobile>555-555-1234</Mobile> 
    <Home>555-555-0001</Home> 
    </Phone> 
</Person> 
<Person age="40" height="70 inches"> 
    <Name>Paul</Name> 
    <Phone> 
    <Mobile>555-555-4567</Mobile> 
    </Phone> 
</Person> 
<Person age="24"> 
    <Name>Susan</Name> 
    <Phone> 
    <Home>555-555-2323</Home> 
    </Phone> 
</Person> 
</People>' 

;with c_Tree (Parent, Node) 
as ( select p.n.value('local-name(..)[1]', 'varchar(max)'), 
       p.n.value('local-name(.)[1]', 'varchar(max)') 
     from @data.nodes('//*[local-name(.) > ""]') p(n) 
    ), 
    c_Expand(lvl, RootName, NodeName) 
as ( select 0, 
       Parent, 
       Node 
     from c_Tree 
     where Parent = '' 
     union all 
     select ce.lvl + 1, 
       ct.Parent, 
       ct.Node 
     from c_Tree ct 
     join c_Expand ce on 
       ce.NodeName = ct.Parent 
) 
select RootName+'>'+NodeName, 
     lvl 
from  c_Expand 
order 
by  lvl asc;