简体   繁体   English

使用SQL查找未知的XML孙子

[英]Finding Unknown XML Grandchildren Using SQL

Is there a way to search through XML Nodes using SQL to see if Parent Nodes have ChildNodes and Grandchildren? 有没有一种方法可以使用SQL搜索XML节点,以查看父节点是否具有ChildNode和孙子级? I'm trying to test some XML files to see if there are any unknown children: 我正在尝试测试一些XML文件,以查看是否有任何未知的子代:

<form>
  <ItemType>New Regular</ItemType>
  <FirstBuyDate>02/01/2007</FirstBuyDate>
  <FirstShipDate>02/05/2007</FirstShipDate>
  <ItemBrand>Gillette Blade/Razors</ItemBrand>
  <ItemDescription>...</ItemDescription>
  <Size>8.00</Size>
  <InnerOffInvoice />
  <MasterOffInvoice />
  <PalletItems>
    <ID>908402</ID> 
    <PalletShipDate>04/03/13</PalletShipDate>
  </PalletItems>
  <ReviewComments />
</form>

In this example, I know that PalletItems has children. 在此示例中,我知道PalletItems有子级。 So I am able to make tables, insert that data accordingly. 这样我就可以制作表格,并相应地插入该数据。 But how can I be sure I've gotten all of the grandchildren of <form> ? 但是如何确定我已经获得<form>所有子孙? What if there are unknown children like with <ItemDescription> - how do I find the children I don't know about? 如果有像<ItemDescription>这样的未知孩子该怎么办-如何找到我不认识的孩子? How can I test all of these nodes to see if <form> has any grandchildren? 我如何测试所有这些节点以查看<form>是否有任何孙代?

This code here showed me how many children had: 这段代码向我展示了有多少个孩子:

SELECT distinct Parent.Items.value('local-name(.)', 'varchar(100)') as 'Item'
    FROM    dbo.FormResults 
    CROSS APPLY xmlformfields.nodes('/form/*') as Parent(Items)

Do any of you have suggestions to find the grandchildren? 你们中有人对找到孙辈有建议吗? Thanks! 谢谢!

Also as a side note - does anyone know how to have this SELECT statement put the children in the order they appear in the xml? 另外,请注意-是否有人知道如何使用此SELECT语句将子级按照它们在xml中出现的顺序排列? Currently when the code grabs the children it will display them in the column in random order: 当前,当代码捕获子级时,它将以随机顺序在列中显示它们:

    Items
1. FirstBuyDate
2. Size
3. ItemType
4. PalletItems... etc. 

I would like them to be displayed like this: 我希望这样显示它们:

    Items:
1. ItemType
2. FirstBuyDate 
3. FirstShipDate
4. ItemBrand... etc. 

---------------------UPDATE---------------------- --------------------- UPDATE ----------------------

Now that we know that (/form//*) will get the children and grandchild thanks to valex 既然我们知道(/ form // *)会由于valex而获得子孙

How can I put the children in one column and the grandchildren in the next? 如何将孩子放在一列中,将孙子放在下一列中? Would it be something like this: 会是这样吗?

SELECT distinct Parent.Items.value('local-name(.)', 'varchar(100)') as 'Child of Form',
CASE when child.items.value('local-name(.)', 'varchar(100)') IS NULL then NULL ELSE 'Has Child' end as 'Grandchild of Form'
FROM    dbo.FormResults 
CROSS APPLY xmlformfields.nodes('/form/*')  as Parent(Items) 
Cross Apply parent.items.nodes('/form//*')  as child(items)

To get all nodes not only from the first level use /form//* with // instead of /form/* 要不仅从第一级获取所有节点,请使用/form//*//而不是/form/*

SELECT distinct Parent.Items.value('local-name(.)', 'varchar(100)') as 'Item'
    FROM    dbo.FormResults 
    CROSS APPLY xmlformfields.nodes('/form//*') as Parent(Items)

SQLFiddle example SQLFiddle示例

To get also parent nodes use syntax ../. 要获取父节点,请使用语法../. in local-name() call. local-name()调用中。 To get an Index of child inside a parent node and order by it you can use XQuery expression 要获取父节点内的子索引并对其排序,可以使用XQuery表达式

for $i in . return count(../*[. << $i])

So the final query with order: 因此,最终查询的顺序为:

SELECT distinct 
          Parent.Items.value('local-name(.)', 'varchar(100)') as 'Item',
          Parent.Items.value('local-name(../.)', 'varchar(100)') as 'ParentItem',
          Parent.Items.value('for $i in . return count(../*[. << $i])','int') 
              as ChildIndex
    FROM    dbo.FormResults 
    CROSS APPLY xmlformfields.nodes('/form//*') as Parent(Items)
    ORDER BY ParentItem,ChildIndex

SQLFiddle example SQLFiddle示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM