我正在使用返回属性信息的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执行一些预处理?
任何帮助都非常感谢(一如既往)。
答案 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/*/*, '
')
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
it smells a bit
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]创建值。