将子节点的文本连接到单个列中

时间:2012-10-21 18:20:24

标签: sql xml sql-server-2008 xpath xquery

我正在使用返回属性信息的API。一些文本信息存储在子节点上,我想将它连接成一个字符串(VARCHAR)。

我的过程是通过web服务获取xml,然后将其传递给proc,它提取xml值并将它们插入到视图中,这是我要回来的xml的片段:

<properties>
    <property propertyid="1234">
        <bullets>
            <bullet>nice garden</bullet>
            <bullet>it smells a bit</bullet>
            <bullet>body under the patio</bullet>
        </bullets>
    </property>
    ...
</properties>

这是如何查询xml以从中提取值的一瞥:

INSERT        
INTO          VProperty
(             PropertyId,
              Description
)
SELECT        P.value('@propertyid', 'INT'),
              NULL -- extract all the bullet text values into a single string
FROM          @xml.nodes('/properties/property')

在这个例子中,我希望能够从xml中提取信息,所以它最终会像这样:

PropertyId    Description
1234          'nice garden\r\nit smells a bit\r\nbody under the patio

这是否可以在纯sql / xml中使用,或者我需要在进入SQL之前对xml执行一些预处理?

任何帮助都非常感谢(一如既往)。

3 个答案:

答案 0 :(得分:4)

这对你有用吗?

DECLARE @XML XML = 
('<properties>
    <property propertyid="1234">
        <bullets>
            <bullet>nice garden</bullet>
            <bullet>it smells a bit</bullet>
            <bullet>body under the patio</bullet>
        </bullets>
    </property>
    <property propertyid="2345">
        <bullets>
            <bullet>bullet 2345_1</bullet>
            <bullet>bullet 2345_2</bullet>
            <bullet>bullet 2345_3</bullet>
        </bullets>
    </property>
</properties>');

SELECT  X.node.value('@propertyid', 'INT'),
        STUFF((SELECT '\r\n' + B.bullet.value('.', 'NVARCHAR(MAX)')
               FROM   X.node.nodes('./bullets/bullet') B ( bullet )
               FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),
              1, 4, '') AS Description
FROM    @xml.nodes('/properties/property') X ( node );

答案 1 :(得分:0)

您可以使用此XQuery(不确定SQL Server 2008的XQuery方言是否完全兼容):

for $pr in /*/property,
    $id in $pr/@propertyid,
    $desc in string-join($pr/*/*, '&#xD;&#xA;')
  return
     (<PropertyId>{string($id)}</PropertyId>,
     <Description>{$desc}</Description>)

使用Saxon和XQSharp(XmlPrime)在提供的XML文档上应用此查询的结果

<properties>
    <property propertyid="1234">
        <bullets>
            <bullet>nice garden</bullet>
            <bullet>it smells a bit</bullet>
            <bullet>body under the patio</bullet>
        </bullets>
    </property>
    ...
</properties>

<强>是

<PropertyId>1234</PropertyId>
<Description>nice garden&#xD;
it smells a bit&#xD;
body under the patio</Description>

答案 2 :(得分:0)

DECLARE @XML XML
SET @XML = 
'<properties>
  <property propertyid="1234">
    <bullets>
      <bullet>nice garden</bullet>
      <bullet>it smells a bit</bullet>
      <bullet>body under the patio</bullet>
    </bullets>
  </property>
  <property propertyid="2345">
    <bullets>
      <bullet>bullet 2345_1</bullet>
      <bullet>bullet 2345_2</bullet>
      <bullet>bullet 2345_3</bullet>
    </bullets>
  </property>
</properties>'

SET @XML = @XML.query('
    for $prop in /properties/property
    return
    <property propertyid="{string($prop/@propertyid)}">
        <description>
        {
            for $bullet in $prop/bullets[1]/bullet
            return
                if ($bullet is $prop/bullets[1]/bullet[1] and $bullet << $prop/bullets[1]/bullet[last()])
                then concat(string($bullet), "\r\n")
                else
                    if ($bullet is $prop/bullets[1]/bullet[last()])
                    then string($bullet)
                    else concat(string($bullet), "\r\n")
        }    
        </description>
    </property>
')

SELECT
Tab.ColXML.value('@propertyid', 'INTEGER') AS PropertyId,
Tab.ColXML.value('description[1]', 'NVARCHAR(128)') AS Description
FROM @XML.nodes('//property') AS Tab(ColXML)

由于MS SQL Server 2005中没有let子句,我必须找到解决方法。

在query()方法的表达式中,我使用2个嵌套&#34;类似循环的&#34;用于选择所需元素的子句。 第一个[for子句]构建[property]元素。第二个[for子句]从[bullet]元素列表中构建[description]元素,[property]的子元素。

[description]将从[bullet]元素列表构建的序列中获取值,如下所示:

第一个但不是最后一个[bullet]将附加&#34; \ r \ n&#34;。

不是第一个而不是最后一个[bullet]也将附加&#34; \ r \ n&#34;。

我们保持其他[bullet]完好无损。

我们连接为每个构建的所有字符串,以便为相关的[description]创建值。