使用 XPath/XQuery 连接同一 XML 元素的所有值

And*_*y M 14 xml sql-server xquery sql-server-2014

我有一个这样的 XML 值:

<R>
  <I>A</I>
  <I>B</I>
  <I>C</I>
  ...
</R>
Run Code Online (Sandbox Code Playgroud)

我想连接所有的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)')
;
Run Code Online (Sandbox Code Playgroud)

但是,我想仅使用 XPath/XQuery 方法来完成所有这些工作,如下所示:

SELECT @MyXml. ? ( ? );
Run Code Online (Sandbox Code Playgroud)

有这样的方法吗?

我在这个方向寻找解决方案的原因是因为我的实际 XML 也包含其他元素,例如:

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)')
;
Run Code Online (Sandbox Code Playgroud)

而且我希望能够将I值提取为单个字符串,并将J值提取为单个字符串,而不必为每个值使用笨拙的脚本。

Mik*_*son 11

这可能对你有用:

select @MyXml.value('/R[1]', 'varchar(50)')
Run Code Online (Sandbox Code Playgroud)

text()从第一个R和下面选取所有元素。

如果你只是想要text()你能做的一切

select @MyXml.value('.', 'varchar(50)')
Run Code Online (Sandbox Code Playgroud)

如果你想的价值观IJ单独做到这一点,而不是。

select @MyXml.query('/R/I/text()').value('.', 'varchar(50)'),
       @MyXml.query('/R/J/text()').value('.', 'varchar(50)')
Run Code Online (Sandbox Code Playgroud)


Tom*_*m V 7

根据您的实际 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);
Run Code Online (Sandbox Code Playgroud)

输出这个:

(No column name) | (No column name) 
---------------  | --------------- 
ABC              | XYZ 
Run Code Online (Sandbox Code Playgroud)

看到这个小提琴