2016-01-20 71 views
2

我有一个Xml文件,我试图解析数据库表。将xml传递到数据库的SQL查询

我有一些代码可以做到这一点,但它不会将代码合理地组织到表格中,因为它会返回没有任何顺序的所有产品和房间。

正如您从下面看到的,xml首先定义了房间名称和RoomId。

接下来是该房间将要出现的产品列表。 这些产品都存储在一个表中,并已分配父母和孩子的ID。

XML然后为不同的房间重复此结构。

我已经采取了一些代码,因为有很多的样式和不必要的代码。

我想要的是一个查询,可以适当地存储这些数据,以便我可以将它存储在数据库中,然后在SQL Server报表生成器中检索它。

欢呼

XML

名称空间

<t:RadDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:t="clr-namespace:Telerik.Windows.Documents.Model;assembly=Telerik.Windows.Documents" 

xmlns:s="clr-namespace:Telerik.Windows.Documents.Model.Styles;assembly=Telerik.Windows.Documents" 

xmlns:r="clr-namespace:Telerik.Windows.Documents.Model.Revisions;assembly=Telerik.Windows.Documents" 

xmlns:n="clr-namespace:Telerik.Windows.Documents.Model.Notes;assembly=Telerik.Windows.Documents" xmlns:th="clr-namespace:Telerik.Windows.Documents.Model.Themes;assembly=Telerik.Windows.Documents" 

xmlns:custom1="clr-namespace:TAS2;assembly=RadRichTextBoxExtensions" 

xmlns:custom2="clr-namespace:;assembly=RadRichTextBoxExtensions" version="1.2" LayoutMode="Paged" LineSpacing="1" LineSpacingType="Auto" ParagraphDefaultSpacingAfter="30" ParagraphDefaultSpacingBefore="30" SelectedBibliographicStyleName="\APA.XSL" StyleName="defaultDocumentStyle"> 

XML片断

<custom1:RoomGroupRangeStart RoomID="26" RoomName="Bathroom" /> 
<custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="Plumbing" ParentID="1"/> 
</custom1:SemanticRangeStart.Product> 
<custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="Central Heating" ParentID="48" /> 
</custom1:SemanticRangeStart.Product> 
<custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="Gas" ParentID="49" /> 
</custom1:SemanticRangeStart.Product> 

第一次尝试

select 
    nodes.node.value('@ID', 'int') Id, 
    nodes.node.value('@Name', 'varchar(max)') Name, 
    nodes.node.value('@ParentID', 'int') ParentId 
from  
    @xml.nodes('//*:Products') nodes (node) 


select 
    nodes.node.value ('@RoomID', 'int') RoomID, 
    nodes.node.value ('@RoomName', 'varchar(max)') RoomName 
from  
    @xml.nodes('//*:RoomGroupRangeStart') nodes (node) 
+0

哪个RDBMS是为了这个?请添加一个标签来指定您是使用'mysql','postgresql','sql-server','oracle'还是'db2' - 或者其他的东西。 –

+0

道歉... SQL服务器 – Simula

+4

这不是一个有效的XML文档 - 没有单一的根元素。还有:显然存在着XML命名空间(从'custom1:'前缀来看) - 但这些命令空间不可见 - 很可能是因为XML文档的某些部分丢失了...... –

回答

1

试试这样说:

我添加了虚拟命名空间和几个重复结构根节点...

DECLARE @x XML= 
'<t:RadDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:t="clr-namespace:Telerik.Windows.Documents.Model;assembly=Telerik.Windows.Documents" 
       xmlns:s="clr-namespace:Telerik.Windows.Documents.Model.Styles;assembly=Telerik.Windows.Documents" 
       xmlns:r="clr-namespace:Telerik.Windows.Documents.Model.Revisions;assembly=Telerik.Windows.Documents" 
       xmlns:n="clr-namespace:Telerik.Windows.Documents.Model.Notes;assembly=Telerik.Windows.Documents" xmlns:th="clr-namespace:Telerik.Windows.Documents.Model.Themes;assembly=Telerik.Windows.Documents" 
       xmlns:custom1="clr-namespace:TAS2;assembly=RadRichTextBoxExtensions" 
       xmlns:custom2="clr-namespace:;assembly=RadRichTextBoxExtensions" version="1.2" LayoutMode="Paged" LineSpacing="1" LineSpacingType="Auto" ParagraphDefaultSpacingAfter="30" ParagraphDefaultSpacingBefore="30" SelectedBibliographicStyleName="\APA.XSL" StyleName="defaultDocumentStyle"> 
    <custom1:RoomGroupRangeStart RoomID="26" RoomName="Bathroom" /> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="Plumbing" ParentID="1" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="Central Heating" ParentID="48" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="Gas" ParentID="49" /> 
    </custom1:SemanticRangeStart.Product> 

    <custom1:RoomGroupRangeStart RoomID="27" RoomName="Test" /> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="Test1" ParentID="1" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="Test2" ParentID="48" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="Test3" ParentID="49" /> 
    </custom1:SemanticRangeStart.Product> 

    <custom1:RoomGroupRangeStart RoomID="28" RoomName="OneMore" /> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="48" Level="1" Name="OneMore1" ParentID="1" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="49" Level="2" Name="OneMore2" ParentID="48" /> 
    </custom1:SemanticRangeStart.Product> 
    <custom1:SemanticRangeStart.Product> 
    <t:Products HasChild="True" ID="50" Level="3" Name="OneMore3" ParentID="49" /> 
    </custom1:SemanticRangeStart.Product> 
</t:RadDocument>'; 
SELECT @x; 

您查询像这样

WITH XMLNAMESPACES('clr-namespace:Telerik.Windows.Documents.Model;assembly=Telerik.Windows.Documents' AS t 
        ,'clr-namespace:TAS2;assembly=RadRichTextBoxExtensions' AS custom1 
        ,DEFAULT 'http://schemas.microsoft.com/winfx/2006/xaml/presentation') 
,Numbered AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowInx 
      ,CASE WHEN The.Node.value('fn:local-name(.)','varchar(max)') = 'RoomGroupRangeStart' THEN 'Room' ELSE 'Product' END AS NodeType 
      ,CAST('<node>' + CAST(The.Node.query('.') AS VARCHAR(MAX)) + '</node>' AS XML) AS TheNode 
    FROM @x.nodes('/t:RadDocument/*') AS The(Node) 
) 
,DistinctRooms AS 
(
    SELECT Numbered.* 
      ,TheNode.value('(*//@RoomID)[1]','int') AS RoomID 
      ,TheNode.value('(*//@RoomName)[1]','varchar(max)') AS RoomName 
    FROM Numbered 
    WHERE NodeType='Room' 
) 

SELECT 
     dr.* 
     ,RelatedProducts.TheNode.value('(*//@HasChild)[1]','bit') AS HasChild 
     ,RelatedProducts.TheNode.value('(*//@ID)[1]','int') AS ProductID 
     ,RelatedProducts.TheNode.value('(*//@Level)[1]','int') AS Level 
     ,RelatedProducts.TheNode.value('(*//@Name)[1]','varchar(max)') AS ProductName 
     ,RelatedProducts.TheNode.value('(*//@ParentID)[1]','int') AS ParentID 

FROM DistinctRooms AS dr 
CROSS APPLY 
(
    SELECT products.* 
    FROM Numbered AS products 
    WHERE products.NodeType='Product' 
     AND products.RowInx BETWEEN dr.RowInx AND (SELECT ISNULL(MIN(x.RowInx),1000000) FROM DistinctRooms AS x WHERE x.RowInx>dr.RowInx) 
) AS RelatedProducts; 

结果

1 26 Bathroom 1 48 1 Plumbing   1 
1 26 Bathroom 1 49 2 Central Heating 48 
1 26 Bathroom 1 50 3 Gas    49 
5 27 Test  1 48 1 Test1   1 
5 27 Test  1 49 2 Test2   48 
5 27 Test  1 50 3 Test3   49 
9 28 OneMore  1 48 1 OneMore1   1 
9 28 OneMore  1 49 2 OneMore2  48 
9 28 OneMore  1 50 3 OneMore3  49 
+0

看起来不错,但是我无法对xml进行任何更改。我将收到它作为我想解析的文档...对不起 – Simula

+0

@Simula没有必要对XML进行更改。我刚刚创建了一个测试场景来让这个运行... – Shnugo

+0

啊好的道歉...如果它们被编号会导致任何问题,如果每个文件稍有不同?即文件a上的空间可能比文件b上的更多产品? – Simula