2012-10-27 36 views
7
declare @xmlsample xml = 
'<root> 
    <solution> 
     <solutionnumber>1</solutionnumber> 
      <productgroup> 
       <productcategory> 
        <price>100</price> 
        <title>Some product</title> 
        <tax>1</tax> 
       </productcategory> 
      </productgroup> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
    <solution> 
     <solutionnumber>2</solutionnumber> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
</root>' 

SELECT 
    --T.C.value('(./ancestor::ns1:solutionNumber)[1]', 'varchar(50)') AS solutionnumber ?? no clue 
    T.C.value('(price)[1]', 'numeric(18,2)') AS price 
    ,T.C.value('(title)[1]', 'varchar(50)') AS title 
    ,T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
FROM @xmlsample.nodes('//node()[title]') AS T(C) 

Biểu diễn XML tôi đang cố gắng băm nhỏ trong SQL Server 2008 r2. Tôi tìm thấy nút "tiêu đề" và lấy các giá trị tôi cần có trong danh mục sản phẩm. Bây giờ tôi muốn nhận được "số giải pháp" tuy nhiên điều này có thể là một hoặc nhiều nút cha trên sản phẩm vì có một số nhóm "sản phẩm nhất định".SQL Server .nodes() Nút cha mẹ XML theo tên

Tôi làm cách nào để kiểm tra các nút cha theo tên ("solutionnumber") cho đến khi tôi tìm thấy? Cảm ơn bạn đã hỗ trợ.

+0

thuật ngữ không chính xác về một phần của tôi. Tuy nhiên, tìm kiếm "solutionnumber". – duffn

Trả lời

2

Có lẽ tôi đã đi về phía sau này. Nhiều ứng dụng chéo sẽ thực hiện công việc. Nhờ một số trợ giúp trên diễn đàn khác.

SELECT 
    --T.C.value('(./ancestor::ns1:solutionNumber)[1]', 'varchar(50)') AS solutionnumber ?? no clue 
    m.c.value('(solutionnumber)[1]', 'int') as solutionnumber 
    ,T.C.value('(price)[1]', 'numeric(18,2)') AS price 
    ,T.C.value('(title)[1]', 'varchar(50)') AS title 
    ,T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
FROM @xmlsample.nodes ('//solution') as m (c) 
cross apply m.c.nodes ('.//node()[title]') as t(C) 
2

Không có cách nào trực tiếp với kiến ​​thức của tôi. Tuy nhiên, bạn có thể sử dụng liên hiệp để tìm theo cách của bạn lên:

SELECT 
    COALESCE(T.C.value('../solutionnumber[1]', 'INT'), 
      T.C.value('../../solutionnumber[1]', 'INT'), 
      T.C.value('../../../solutionnumber[1]', 'INT')) solutionnumber, 
    T.C.value('(price)[1]', 'numeric(18,2)') AS price, 
    T.C.value('(title)[1]', 'varchar(50)') AS title, 
    T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
    FROM 
    @xmlsample.nodes('//node()[title]') AS T (C) 

Lưu ý rằng <solutionnumber> thực sự là một người anh em của một trong những tổ tiên chứ không phải là tổ tiên của chính nó.

Giải pháp này yêu cầu bạn phải biết độ sâu tối đa trước thời hạn.


Bạn cũng có thể sử dụng giải pháp này, nếu bạn thay vì đi về phía trước hơn ngược:

SELECT solutionNodes.solutionNode.value('solutionnumber[1]','INT') AS solutionnumber, 
    T.C.value('(price)[1]', 'numeric(18,2)') AS price, 
    T.C.value('(title)[1]', 'varchar(50)') AS title, 
    T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
FROM @xmlsample.nodes('//solution') AS solutionNodes (solutionNode) 
CROSS APPLY (SELECT solutionNodes.solutionNode.query('.')) solutions(solutionXML) 
CROSS APPLY solutions.solutionXML.nodes('//node()[title]') T (C) 

Nó sử dụng thực tế là> thẻ <solutionnumber là một đứa trẻ trực tiếp của a> thẻ <solution. Đầu tiên, hãy tìm tất cả các thẻ <solution. Hơn tất cả các hậu duệ của nó được tìm thấy với một thập tự áp dụng. Bởi vì bạn không thể sử dụng các nút chức năng trên một nút có tính toán của "truy vấn ('.')" Ở giữa.

Khác với giải pháp trên, điều này có thể xử lý bất kỳ khoảng cách nào giữa thẻ <solution> thẻ abd <title>.

1

Máy chủ SQL không hỗ trợ quay lại tổ tiên, vì vậy đây là cách vòng tròn caching con trỏ đến tổ tiên trong khi giảm dần vào XML.

declare @xmlsample xml = 
'<root> 
    <solution> 
     <solutionnumber>1</solutionnumber> 
      <productgroup> 
       <productcategory> 
        <price>100</price> 
        <title>Some product</title> 
        <tax>1</tax> 
       </productcategory> 
      </productgroup> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
    <solution> 
     <solutionnumber>2</solutionnumber> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
</root>'; 

WITH Xml_CTE AS 
(
    SELECT node.query('*') AS children, 
      node.value('fn:local-name(.)','varchar(100)') localName, 
      node.exist('title') IsTitleParent, 
      CAST(null as xml) as solution 
     FROM @xmlsample.nodes('/*') AS root(node) 
    UNION ALL 
    SELECT node.query('*') AS children, 
      node.value('fn:local-name(.)','varchar(100)') localName, 
      node.exist('title') IsTitleParent, 
      CASE WHEN node.value('fn:local-name(.)', 'varchar(100)') = 'solution' 
       THEN node.query('.') 
       ELSE solution END 
     FROM Xml_CTE x 
CROSS APPLY x.children.nodes('*') AS child(node) 
) 
SELECT solution.value('(solution/solutionnumber/text())[1]', 'int') solutionNumber 
     ,children.value('(price)[1]', 'numeric(18,2)') price 
     ,children.value('(title)[1]', 'varchar(50)') title 
     ,children.value('(tax)[1]', 'numeric(18,2)') tax 
    FROM Xml_CTE 
WHERE IsTitleParent = 1 -- matches .nodes('//node()[title]') 
OPTION (MAXRECURSION 0); 
0

này sẽ làm việc một cách hoàn hảo ...

Declare @SomeXML XML 
SET @SomeXML = '<SomeValue>GGGG</SomeValue><SomeValue>MMMM</SomeValue><SomeValue>AAA</SomeValue>' 

select ROW_NUMBER() over (order by b), b.value('.', 'varchar(50)') 
from @SomeXML.nodes('(/SomeValue)') AS a(b) 
Các vấn đề liên quan