データベースに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>
タグをSelectionとして取得し、残りの値を連結文字列として取得する必要があります。
私は次のクエリを試しました:
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 2番目
ul number Selection Value
--------- --------- ------------
1 Ab AD
1 Ag AL
2 Bb BD
2 Bg BL
列ul番号とh4番号の関係。私はできません。
これは正確にはエレガントではありませんが、仕事をしているようです。
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 |
+----------+-----------+-------+
質問の目的の結果テーブルが「残りの値を連結された文字列として」返さないので、これはあなたが望むものだと思います
ノード
h4
とul
の間の通信を確立しようとしています。
<<
および>>
演算子を使用して、ドキュメントの順序でノードが別のノードの前か後かを確認できます。これを位置の述語[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>