2011-07-11 5 views
2

xmlは、興味のある要素の名前/パスを持つテーブルとテーブルに格納されています。SQL ServerでXQueryを使用して要素の名前をハードコーディングせずにXMLから値を抽出する方法はありますか

ハードコーディングパスや要素の名前を使わずにこれらの要素の値を抽出したいと思います。私のXMLの構造は変更されません、それは常に親/子/要素があります。

xmlとtableを結合して要素の値を取得することはできますか?

以下は私が得ることのできる例です。 ChildNodeとElementのJOINにこのソリューションを拡張することは可能だと思いますが、.query().value()をChildNodeとElementにどのように使用するかはわかりません。

ありがとうございました。

DECLARE @xml xml 
SET @xml = 
'<Products> 
    <RedProduct> 
     <Details_RedProduct> 
     <Width>1</Width> 
     <Depth>2</Depth> 
     <Weight>3</Weight> 
     </Details_RedProduct> 
    </RedProduct> 
    <GreenProduct> 
     <Details_GreenProduct> 
     <Width>4</Width> 
     <Depth>5</Depth> 
     <Height>6</Height> 
     </Details_GreenProduct> 
     </GreenProduct> 
    <BlueProduct> 
     <Details_BlueProduct> 
     <Width>7</Width> 
     <Depth>8</Depth> 
     <Lenght>9</Lenght> 
     </Details_BlueProduct> 
    </BlueProduct> 
</Products>' 

DECLARE @ProductElement table (ProductNode nvarchar(100), ChildNode nvarchar(100), Element nvarchar(20)) 
INSERT INTO @ProductElement SELECT 'RedProduct','','Width' 
INSERT INTO @ProductElement SELECT 'GreenProduct','','Width' 
INSERT INTO @ProductElement SELECT 'GreenProduct','','Height' 
UPDATE @ProductElement SET ChildNode = 'Details_' + ProductNode 

SELECT ProductsCollection.query('local-name(.)').value('.','nvarchar(100)') as TestOutput 
FROM @xml.nodes('//Products/*') productsXml (ProductsCollection) 
INNER JOIN @ProductElement el ON el.ProductNode = ProductsCollection.query('local-name(.)').value('.','nvarchar(100)') 

答えて

1

あなたのXQuery式でsql:column()を使用して、必要なノードを取得するためにlocal-name(.)と比較することができます。

select PE.ProductNode, 
     PE.ChildNode, 
     PE.Element, 
     T.Col.value('.', 'int') as ElementValue 
from @ProductElement as PE 
    cross apply @xml.nodes('/Products/*[local-name(.) = sql:column("PE.ProductNode")] 
            /*[local-name(.) = sql:column("PE.ChildNode")] 
            /*[local-name(.) = sql:column("PE.Element")]') as T(Col) 

結果:

ProductNode   ChildNode   Element    ElementValue 
-------------------- -------------------- -------------------- ------------ 
RedProduct   Details_RedProduct Width    1 
GreenProduct   Details_GreenProduct Width    4 
GreenProduct   Details_GreenProduct Height    6 

編集: 代わりにフィールドに参加使用しています別のバージョン。それはかもしれないあなたのデータがどのように見えるかに応じてより良いパフォーマンスを持っています。最初のバージョンは@ProductElementの各行のXMLを解析し、2番目のバージョンはXMLを切り捨て、@ProductElementに結合するためにXMLを切り捨てます。

select PE.ProductNode, 
     PE.ChildNode, 
     PE.Element, 
     X.ElementValue 
from @ProductElement as PE 
    inner join (
       select T1.Col.value('local-name(.)', 'varchar(100)') as ProductNode, 
         T2.Col.value('local-name(.)', 'varchar(100)') as ChildNode, 
         T3.Col.value('local-name(.)', 'varchar(100)') as Element, 
         T3.Col.value('.',    'varchar(100)') as ElementValue 
       from @xml.nodes('/Products/*') as T1(Col) 
       cross apply T1.Col.nodes('*') as T2(Col) 
       cross apply T2.Col.nodes('*') as T3(Col) 
      ) as X 
    on PE.ProductNode = X.ProductNode and 
     PE.ChildNode = X.ChildNode and 
     PE.Element = X.Element 
+0

私の場合は2番目のオプションが少し速いです。 あなたの答えと2つのオプションを提供していただきありがとうございます。 –

関連する問題