Làm cách nào để đọc mã HTML dưới dạng XML và nhận đầu ra như mẫu trong sql?


11

Tôi có mã HTML được lưu trữ trong cơ sở dữ liệu và tôi muốn đọc nó dưới dạng XML.

Mã của tôi:

http://rextester.com/RMEHO89992

Đây là một ví dụ về mã HTML tôi có:

<div>
  <section>
       <h4>
         <span> A </span>
        </h4>
        <ul>
           <li>
              <span> Ab</span>
                     AD
              <span> AC </span>
           </li>
           <li>
              <span> Ag</span>
              <span> AL </span>
           </li>
        </ul>
        <h4>
              <span> B </span>
       </h4>
       <ul>
           <li>
              <span> Bb</span>
                     BD
              <span> BC </span>
           </li>
           <li>
              <span> Bg</span>
              <span> BL </span>
           </li>
        </ul>
   </section>
</div>

và đây là một ví dụ về đầu ra tôi cần:

Category         Selection        Value                    
---------        ---------        ------------             
A                Ab               AD                  
A                Ag               AL                       
B                Bb               BD                   
B                Bg               BL                       

Tôi cần lấy giá trị bên trong <h4>thẻ dưới dạng a Category, <span>thẻ đầu tiên là Lựa chọn và phần còn lại của các giá trị dưới dạng chuỗi nối.

Tôi đã thử truy vấn sau:

SELECT 
    (  isnull(t.v.value('(h4/span/span[1]/text())[1]','nvarchar(max)'),'') 
     + isnull(t.v.value('(h4/span/text())[1]','nvarchar(max)'),'')
     + isnull(t.v.value('(h4/span/span[2]/text())[2]','nvarchar(max)'),'')
    ) AS [Category],
    (  isnull(c.g.value('(span[1]/text())[1]','nvarchar(max)'),'')
     + isnull(c.g.value('(span[1]/span/text())[1]','nvarchar(max)'),'')
     + isnull(c.g.value('(span[1]/text())[2]','nvarchar(max)'),'')
    ) AS [Selection],
    (  isnull(c.g.value('(span[2]/text())[1]','nvarchar(max)'),'')
     + isnull(c.g.value('(span[2]/span/text())[1]','nvarchar(max)'),'')
     + isnull(c.g.value('(span[2]/text())[2]','nvarchar(max)'),'')
    ) AS [Value]
FROM @htmlXML.nodes('div/section') as t(v)
CROSS APPLY t.v.nodes('./ul/li') AS c(g) 

:

SELECT 
       t.v.value('.','nvarchar(max)')
       ,
     --( isnull(t.v.value('(h4/span/span[1]/text())[1]','nvarchar(max)'),'')+isnull(t.v.value('(h4/span/text())[1]','nvarchar(max)'),'')+isnull(t.v.value('(h4/span/span[2]/text())[2]','nvarchar(max)'),''))AS [Category],

          ( isnull(c.g.value('(span[1]/text())[1]','nvarchar(max)'),'')+isnull(c.g.value('(span[1]/span/text())[1]','nvarchar(max)'),'')+isnull(c.g.value('(span[1]/text())[2]','nvarchar(max)'),''))AS [Selection]

           ,
         ( isnull(c.g.value('(span[2]/text())[1]','nvarchar(max)'),'')+isnull(c.g.value('(span[2]/span/text())[1]','nvarchar(max)'),'')+isnull(c.g.value('(span[2]/text())[2]','nvarchar(max)'),''))AS [Value]
    FROM    @htmlXML.nodes('div/section/h4/span') as t(v)
    CROSS APPLY @htmlXML.nodes('div/section/ul/li') AS c(g)

Nhưng nó chỉ nhận được danh mục đầu tiên và không nhận được tất cả các giá trị togheter.

Category         Selection        Value
---------        ---------        ------------
A                Ab               AC 
B                Ab               AC 
A                Ag               AL
B                Ag               AL 
A                Bb               BC
B                Bb               BC 
A                Bg               BL 
B                Bg               BL 

Có thể có N loại và các giá trị có thể hoặc không thể nằm trong <span>thẻ. Làm thế nào tôi có thể nhận được tất cả các loại với giá trị tương ứng của họ? hoặc nhận được:

category              h4 number
--------            -----------
 A                     1
 B                     2
  • 1, mean = h4 trước, 2, mean = h4 giây
 ul number         Selection        Value                    
    ---------        ---------        ------------             
    1                Ab               AD                  
    1                Ag               AL                       
    2                Bb               BD                   
    2                Bg               BL       

mối quan hệ giữa số ul cột và số h4. tôi không thể.


1
Bạn có chắc chắn kết quả mong đợi là chính xác? Không nên AD ACcho hàng đầu tiên trong cột thứ ba?
Mikael Eriksson

Tôi đang cố gắng thiết lập giao tiếp giữa các nút` h4` và `ul`.
RedArmy

Câu trả lời:


7

Điều này không chính xác thanh lịch nhưng dường như để thực hiện công việc.

DECLARE @X XML = REPLACE(REPLACE(@S, '<h4>', '<foo><h4>'), '</ul>', '</ul></foo>')

SELECT Category = x.value('../../h4[1]/span[1]', 'varchar(10)'),
       Selection = x.value('descendant-or-self::text()[1]', 'varchar(10)'),
       Value = REPLACE(
                REPLACE(
                 REPLACE(
                  LTRIM(
                   RTRIM(
                    REPLACE(
                     REPLACE(
                      CAST(x.x.query('fn:data(descendant-or-self::text()[fn:position() > 1])') AS VARCHAR(MAX))
                     , char(10), '')
                    , char(13), '')
                   )
                  )
                 , '  ', ' |')
                , '| ', '')
               , '|', '')
FROM   @X.nodes('div/section/foo/ul/li') x(x)
ORDER  BY Category,
          Selection

Trả về

+----------+-----------+-------+
| Category | Selection | Value |
+----------+-----------+-------+
|  A       |  Ab       | AD AC |
|  A       |  Ag       | AL    |
|  B       |  Bb       | BD BC |
|  B       |  Bg       | BL    |
+----------+-----------+-------+

Tôi giả sử đây là những gì bạn muốn vì bảng kết quả mong muốn trong câu hỏi không trả về "phần còn lại của các giá trị dưới dạng chuỗi nối"


14

Tôi đang cố gắng thiết lập giao tiếp giữa các nút h4ul.

Bạn có thể sử dụng toán tử <<and >>để kiểm tra xem một nút nằm trước hay sau một nút khác theo thứ tự tài liệu. Kết hợp điều đó với một vị ngữ trên vị trí [1], để có được sự xuất hiện đầu tiên cũng theo thứ tự tài liệu.

select H4.X.value('(span/text())[1]', 'varchar(10)') as Section,
       UL.X.query('.') as UL
from @X.nodes('/div/section/h4') as H4(X)
  cross apply H4.X.nodes('(let $h4 := . (: Save current h4 node :)
                           return /div/section/ul[$h4 << .])[1]') as UL(X);

rextester:

<<>>được gọi là Toán tử so sánh thứ tự nút

Nếu bạn có một đoạn XML như thế này:

<N1>1</N1>
<N2>2</N2>
<N3>3</N3>
<N4>4</N4>
<N5>5</N5>

bạn có thể nhận được tất cả các nút trước khi xuất hiện lần đầu tiên N3với truy vấn này:

select @X.query('/*[. << /N3[1]]');

Kết quả:

<N1>1</N1>
<N2>2</N2>

/*sẽ cung cấp cho bạn tất cả các nút gốc. Những gì được bao bọc trong []là một vị ngữ. .là nút hiện tại và/N3[1] là nút N3 đầu tiên theo thứ tự tài liệu ở cấp gốc. Vì vậy, từ mỗi nút gốc, bạn nhận được các nút đi trướcN3 .

Đây là gần như cùng một truy vấn, chỉ có bạn nhận được các nút theoN3 nút đầu tiên :

select @X.query('/*[. >> /N3[1]]');
<N4>4</N4>
<N5>5</N5>

Để chỉ lấy nút đầu tiên sau N3nút đầu tiên , bạn thêm biến vị ngữ [1]:

select @X.query('/*[. >> /N3[1]][1]');
<N4>4</N4>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.