HTML kodunu XML olarak nasıl okuyabilir ve çıktıyı sql'deki örnek gibi nasıl alabilirim?


11

Veri tabanında saklanan HTML kodum var ve XML olarak okumak istiyorum.

Kodlarım:

http://rextester.com/RMEHO89992

Bu sahip olduğum HTML kodunun bir örneğidir:

<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>

ve bu ihtiyacım olan çıktıya bir örnek:

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

Bir <h4>etiket olarak değeri Category, <span>Seçim olarak ilk etiket ve bitmiş bir dize olarak değerlerin geri kalanı almak gerekir.

Aşağıdaki sorguyu denedim:

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) 

ve :

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)

Ancak sadece ilk kategoriyi alır ve tüm değerleri bir araya getirmez.

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 

N kategorisi olabilir ve değerler <span>etiketlerin içinde olabilir veya olmayabilir . Tüm kategorileri karşılık gelen değerleriyle nasıl alabilirim? veya alın:

category              h4 number
--------            -----------
 A                     1
 B                     2
  • 1, ortalama = h4 önce, 2, ortalama = h4 saniye
 ul number         Selection        Value                    
    ---------        ---------        ------------             
    1                Ab               AD                  
    1                Ag               AL                       
    2                Bb               BD                   
    2                Bg               BL       

sütun ul sayısı ve h4 sayısı arasındaki ilişki. yapamam.


1
Beklenen sonucun doğru olduğundan emin misiniz? AD ACÜçüncü sütundaki ilk satır için olmamalı mı ?
Mikael Eriksson

`H4` ve` ul` düğümleri arasında iletişim kurmaya çalışıyorum.
RedArmy

Yanıtlar:


7

Bu tam olarak zarif değil ama işi yapıyor gibi görünüyor.

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

Hangi döndürür

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

Sorunda istenen sonuç tablosu "birleştirilmiş dize olarak değerlerin geri kalanı" döndürmüyor gibi istediğinizi varsayalım


14

Düğümler h4ve arasında iletişim kurmaya çalışıyorum ul.

Düğümün belge sırasında başka bir düğümden önce mi yoksa sonra mı olduğunu kontrol etmek için <<ve >>işlecini kullanabilirsiniz . [1]İlk sıralamayı belge sırasına göre elde etmek için, konumu bir yüklemle birleştirin .

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:

<<ve Düğüm Sırası Karşılaştırma İşleçleri>> olarak adlandırılır

Bunun gibi bir XML parçanız varsa:

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

N3bu sorgu ile ilk oluşumundan önce tüm düğümleri alabilirsiniz :

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

Sonuç:

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

/*size tüm kök düğümleri verecektir. İçinde yer []alan bir yüklemdir. .geçerli düğümdür ve /N3[1]kök düzeyinde belge düzenindeki ilk N3 düğümüdür. Böylece her bir kök düğümden önce gelen düğümleri alırsınız N3.

İşte neredeyse aynı sorgu, sadece ilk düğümü takip eden düğümleri alırsınız N3:

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

Yalnızca ilk düğümden sonraki ilk düğümü almak N3için yüklemi eklersiniz [1]:

select @X.query('/*[. >> /N3[1]][1]');
<N4>4</N4>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.