次のようなXML値があります。
_<R>
<I>A</I>
<I>B</I>
<I>C</I>
...
</R>
_
すべてのI
値を連結し、それらを単一の文字列として返したい:_ABC...
_。
これで、XMLを細断処理し、結果をノードレスXMLとして集約し、.values('text()[1]', ...)
を結果に適用できることがわかりました。
_SELECT
(
SELECT
n.n.value('text()[1]', 'varchar(50)') AS [text()]
FROM
@MyXml.nodes('/R/I') AS n (n)
FOR XML
PATH (''),
TYPE
).value('text()[1]', 'varchar(50)')
;
_
ただし、XPath/XQueryメソッドのみを使用して、次のようなことをすべて実行したいと思います。
_SELECT @MyXml. ? ( ? );
_
そのような方法はありますか?
この方向で解決策を探しているのは、実際のXMLには他の要素も含まれているためです。たとえば、
_<R>
<I>A</I>
<I>B</I>
<I>C</I>
...
<J>X</J>
<J>Y</J>
<J>Z</J>
...
</R>
_
また、I
の値を1つの文字列として抽出することも、J
の値を1つの文字列として抽出することもできます。それぞれに扱いにくいスクリプトを使用する必要はありません。
これはあなたのために働くかもしれません:
_select @MyXml.value('/R[1]', 'varchar(50)')
_
最初のR
以下からすべてのtext()
要素を取得します。
すべてが必要な場合はtext()
を実行できます
_select @MyXml.value('.', 'varchar(50)')
_
I
とJ
の値を別々にしたい場合は、代わりにこれを行ってください。
_select @MyXml.query('/R/I/text()').value('.', 'varchar(50)'),
@MyXml.query('/R/J/text()').value('.', 'varchar(50)')
_
実際のXML構造によっては、次のようなループの使用を検討できます。
DECLARE @xml XML
SELECT @xml = '<R>
<I>A</I>
<I>B</I>
<I>C</I>
<J>X</J>
<J>Y</J>
<J>Z</J>
</R>'
SELECT
Tbl.Col.query('for $i in I return $i').value('.', 'nvarchar(max)'),
Tbl.Col.query('for $i in J return $i').value('.', 'nvarchar(max)')
FROM @xml.nodes('R') Tbl(Col);
これはこれを出力します:
(No column name) | (No column name)
--------------- | ---------------
ABC | XYZ
これを見てください フィドル
要素と値が本当に短くてはっきりしている場合、これはうまくいきます:
declare @s varchar(99) = '<R><I>A</I><I>B</I><I>C</I></R>';
select
@s,
REPLACE(TRANSLATE ( @s, '<>I/R', ' '), ' ', '');
しかし、自明ではないXMLの場合は、困難な場合があります。