HTML로 XML 코드를 읽고 SQL의 샘플과 같은 출력을 얻는 방법은 무엇입니까?


11

데이터베이스에 HTML 코드가 저장되어 있으며 XML로 읽고 싶습니다.

내 코드 :

http://rextester.com/RMEHO89992

이것은 내가 가진 HTML 코드의 예입니다.

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

그리고 이것은 내가 필요한 출력의 예입니다.

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

<h4>태그 내부의 값 을로 Category, 첫 번째 <span>태그를 선택으로, 나머지 값을 연결된 문자열로 가져와야합니다.

다음 쿼리를 시도했습니다.

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)

그러나 첫 번째 범주 만 가져오고 모든 값을 얻을 수는 없습니다.

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 개의 범주가있을 수 있으며 값은 <span>태그 안에 있거나 없을 수 있습니다 . 해당 범주의 값으로 모든 범주를 얻으려면 어떻게해야합니까? 또는 얻을 :

category              h4 number
--------            -----------
 A                     1
 B                     2
  • 1, 평균 = h4 우선, 2, 평균 = h4 초
 ul number         Selection        Value                    
    ---------        ---------        ------------             
    1                Ab               AD                  
    1                Ag               AL                       
    2                Bb               BD                   
    2                Bg               BL       

열 ul 수와 h4 수 사이의 관계. 나는 cannt.


1
예상 결과가 정확합니까? AD AC세 번째 열의 첫 번째 행 이 아니어야합니까 ?
Mikael Eriksson

노드 h4와 ul 사이에 통신을 설정하려고합니다.
RedArmy

답변:


7

이것은 정확히 우아하지는 않지만 일을하는 것처럼 보입니다.

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

어떤 반환

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

질문의 원하는 결과 테이블이 "연결된 문자열로 나머지 값"을 반환하지 않기 때문에 이것이 원하는 것으로 가정합니다.


14

노드 h4와 사이의 통신을 설정하려고합니다 ul.

<<and >>연산자를 사용하여 노드가 문서 순서에서 다른 노드 이전 또는 이후인지 확인할 수 있습니다 . [1]문서 순서로 첫 번째 항목을 얻으려면 위치에 술어를 결합하십시오 .

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

익스트림 :

<<>>호출 노드 순서 비교 연산자

다음과 같은 XML 조각이있는 경우 :

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

N3이 쿼리 에서 처음 발생하기 전에 모든 노드를 가져올 수 있습니다.

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

결과:

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

/*모든 루트 노드를 제공합니다. 안에 포함 된 []것은 술어입니다. .현재 노드이며 /N3[1]루트 레벨에서 문서 순서의 첫 번째 N3 노드입니다. 따라서 각 루트 노드에서 이전 노드를 얻습니다 N3.

다음은 거의 동일한 쿼리이며 첫 번째 노드 를 따르는 노드 만 가져옵니다 N3.

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

첫 번째 노드 다음에 첫 번째 노드 만 가져 오려면 N3술어를 추가하십시오 [1].

select @X.query('/*[. >> /N3[1]][1]');
<N4>4</N4>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.