2013-06-29 35 views
0

我想從xml中的所有數據轉換爲SQL Server中的字符串。所有數據從XML到節點的路徑

所以假設我有這樣的XML:

<node1> 
    <node2> 
    <node3 att1="1"> 
     456 
    </node3> 
    <node4 att2="25"/> 
    </node2> 
</node1> 

我要的是得到這樣的數據:

╔══════════════════════════╦════════════╗ 
║      Name ║  Value ║ 
╠══════════════════════════╬════════════╣ 
║ node1/node2/node3  ║  456 ║ 
║ node1/node2/node3/@att1 ║   1 ║ 
║ node1/node2/node3/@att2 ║   25 ║ 
╚══════════════════════════╩════════════╝ 

我不記得了XPath的不夠好,我可以做到這一點遞歸查詢(SQL FIDDLE):

declare @data xml 

set @data = '<root><node2><node3 att1="1">ggf</node3><node4 att2="25"/></node2></root>' 

;with 
CTE_xpath as (
    select 
    T.C.value('local-name(.)', 'nvarchar(max)') as Name, 
    T.C.query('./*') as elements, 
    T.C.value('text()[1]', 'nvarchar(max)') as Value 
    from @data.nodes('*') as T(c) 

    union all 

    select 
    p.Name + '/' + T.C.value('local-name(.)', 'nvarchar(max)') as Name, 
    T.C.query('./*') as elements, 
    T.C.value('text()[1]', 'nvarchar(max)') as Value 
    from CTE_xpath as p 
    cross apply p.elements.nodes('*') as T(C) 
    union all 

    select 
    p.Name + '/' + 
    T.C.value('local-name(..)', 'nvarchar(max)') + '/@' + 
    T.C.value('local-name(.)', 'nvarchar(max)') as Name, 
    null as elements, 
    T.C.value('.', 'nvarchar(max)') as Value 
    from CTE_xpath as p 
    cross apply p.elements.nodes('*/@*') as T(C) 
) 
select Name, Value 
from CTE_xpath 
where Value is not null 

你怎麼想,什麼是做這個塔斯的最佳方式K +

+0

Xpath將選擇節點好吧,它不會返回你的名字。你爲什麼在SQL中做這個?這可能是有用的http://stackoverflow.com/questions/14747762/convert-xml-to-key-value-pair-notation –

+0

以及它只是一個有趣的問題:)。當我想以某種方式處理數據時,SQL對於我來說是第一語言。 感謝您的鏈接 –

+0

我對好奇心沒有任何問題,並且總是很高興爲您的弓另一個字符串,但它不會是我的第一個選擇。 –

回答

2

這裏有一個比託尼·霍普金森的評論明顯更簡潔的解決方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
    <items> 
     <xsl:apply-templates 
      select="(//* | //@*)[text()[normalize-space()] or 
            not(self::*) and normalize-space()]" /> 
    </items> 
    </xsl:template> 

    <xsl:template match="@* | node()"> 
    <item value="{normalize-space()}"> 
     <xsl:attribute name="path"> 
     <xsl:apply-templates select="ancestor-or-self::node()[parent::node()]" 
          mode="path" /> 
     </xsl:attribute> 
    </item> 
    </xsl:template> 

    <xsl:template match="@* | node()" mode="path"> 
    <xsl:value-of select="concat('/', 
           substring('@', 1, not(self::*)), 
           name())"/> 
    </xsl:template> 
</xsl:stylesheet> 

當你的樣品輸入運行的結果是:

<items> 
    <item value="456" path="/node1/node2/node3" /> 
    <item value="1" path="/node1/node2/node3/@att1" /> 
    <item value="25" path="/node1/node2/node4/@att2" /> 
</items> 

應該在理論上可以使用更簡潔直觀

<xsl:apply-templates select="//*[text()[normalize-space()]] | 
          //@*[normalize-space()]" /> 

但由於某些原因,這個cr灰燼我的整個IDE,我無法弄清楚爲什麼。

相關問題