2014-05-13 66 views
1

我正在嘗試編寫一個SQL查詢,它將取入未定義架構(YAY!)的XML對象,並將其轉換爲ElementName,Value列的兩列表。在一段時間後,我能夠獲得簡單的查詢(我不是任何方式的SQL人員)。元素層級的SQL XML解析查詢

DECLARE @strXml XML 
SET @strXml = '<xml> 
    <FirstName>TEST</FirstName> 
    <LastName>PERSON</LastName> 
    <DOB>1/1/2000</DOB> 
    <TestObject> 
    <SomeProperty>CHECKED</SomeProperty> 
    <EmbeddedObject> 
     <SomeOtherProperty>NOT CHECKED</SomeOtherProperty> 
    </EmbeddedObject> 
    </TestObject> 
</xml>' 

DECLARE @XmlMappings TABLE 
(  
    NodeName VARCHAR(64), 
    Value VARCHAR(128) 
) 
INSERT INTO @XmlMappings 
SELECT doc.col.value('fn:local-name(.)[1]', 'varchar(64)') AS ElementName, 
     doc.col.value('.', 'varchar(128)') AS Value 
FROM @strXml.nodes('/xml/*') doc(Col) 
SELECT * FROM @XmlMappings 

此查詢可以處理指定XML只有第一級元素的簡單條件。但是,像TestObject和EmbeddedObject這樣的元素最終會變平。我正在尋找的是獲得某種類型的映射,如

ElementName         | Value 
===================================================== 
FirstName         | TEST 
LastName         | PERSON 
DOB           | 1/1/2000 
TestObject.SomeProperty      | CHECKED 
TestObject.EmbeddedObject.SomeOtherProperty | NOT CHECKED 

對我而言,困難的部分是層次結構。運營商。我不在乎它是否是一些其他的分隔符。即獲得輸出,它只是讓輸出完成,而我對SQL中的XML知之甚少,甚至無法知道要查詢什麼。

請注意,我也可以不使用OPENXML,因爲這期望部署在目前不支持該功能的SQL Azure上。

回答

2

隨着CTEcross apply

;with cte as 
(
    select 
     convert(varchar(100), x.n.value('fn:local-name(.)','varchar(100)')) as path, 
     convert(varchar(100), x.n.value('fn:local-name(.)','varchar(100)')) AS name, 
     x.n.query('*') AS children, 
     x.n.value('.','varchar(1000)') as value 
    from @strxml.nodes('/xml/*') AS x(n) 
    union all 
    select 
     convert(varchar(100), x.path + '.' + c.n.value('fn:local-name(.)','varchar(100)')), 
     convert(varchar(100), c.n.value('fn:local-name(.)','varchar(100)')) , 
     c.n.query('*'), 
     c.n.value('.','varchar(1000)') 
    from cte x 
     cross apply x.children.nodes('*') AS c(n) 
) 

select path, value from cte where datalength(children) = 5 
+0

WOW!完美的作品。我一直在努力研究它究竟是如何工作的,並且認爲我現在已經把它放下了。我唯一的問題是爲什麼datalength(children)上的過濾器= 5?這意味着什麼?我已經證明,它仍然適用於進一步的嵌套對象,所以沒有問題,只是真正的興趣。 – tostringtheory

+0

@tostringtheory它過濾出有孩子的結果集的元素。不知道爲什麼字段大小是5而不是0,但這是它的方式:) – podiluska