选择多个节点xml

时间:2013-03-13 15:41:47

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

我正在从ntext字段中检索xml格式的文本(下面一行的样本格式):

<root>
  <DocInfo>
    <CompanyName>Some Company</CompanyName>
    <WebsiteUrl>http://www.someurl.com</WebsiteUrl>
    <PrimaryServices>Benefits Administration</PrimaryServices>
    <PrimaryServices>Payroll Processing</PrimaryServices>
    <SecondaryServices>Background Checking</SecondaryServices>
    <SecondaryServices>HR Outsourcing</SecondaryServices>
    <SecondaryServices>Comp & Benefits</SecondaryServices>
    <SecondaryServices>Administration</SecondaryServices>
  </DocInfo>
</root>

使用这个sql我正在检索单节点值:

select  @xmlString = COALESCE(@xmlString + '', '') + cast(content_html as nvarchar(max)) FROM  content where folder_id = 18
set @xmlString = replace(@xmlString,'<?xml version="1.0" encoding="UTF-16" standalone="yes"?>','')
set @XML = cast(@xmlString as xml)

Select
T.N.value('CompanyName[1]', 'varchar(250)') as CompanyName,
T.N.value('WebsiteUrl[1]', 'varchar(250)') as WebsiteUrl,
T.N.value('PrimaryServices[1]', 'varchar(250)') as PrimaryServices,
T.N.value('SecondaryServices[1]', 'varchar(250)') as SecondaryServices,
T.N.value('Description[1]', 'varchar(max)') as Description
from @XML.nodes('/root/DocInfo') as T(N)

这适用于单节点值(CompanyName,WebsiteUrl)。但是,它没有正确插入具有多个值的节点(如PrimaryServices和SecondaryServices - 每个节点可能有0到16个节点)。如何将这些可变长度的多节点值放入这些列中?

感谢您的帮助

1 个答案:

答案 0 :(得分:3)

要将多个节点作为逗号分隔值,您可以使用for xml path('')技巧的变体。使用碎片XML(TN)作为子查询中的源来获取您感兴趣的节点.xQuery ... substring(text()[1]) ...部分用于删除额外的逗号并从中获取逗号分隔值。由for xml创建的XML。

select
  T.N.value('(CompanyName/text())[1]', 'varchar(250)') as CompanyName,
  T.N.value('(WebsiteUrl/text())[1]', 'varchar(250)') as WebsiteUrl,
  (
    select ', '+P.N.value('text()[1]', 'varchar(max)')
    from T.N.nodes('PrimaryServices') as P(N)
    for xml path(''), type
  ).value('substring(text()[1], 2)', 'varchar(max)') as PrimaryServices,
  (
    select ', '+S.N.value('text()[1]', 'varchar(max)')
    from T.N.nodes('SecondaryServices') as S(N)
    for xml path(''), type
  ).value('substring(text()[1], 2)', 'varchar(max)') as SecondaryServices,
  T.N.value('(Description/text())[1]', 'varchar(max)') as Description
from @XML.nodes('/root/DocInfo') as T(N)

如果您想要一列中的所有服务,则可以在子查询的节点部分中使用不同的xPath。

select
  T.N.value('(CompanyName/text())[1]', 'varchar(250)') as CompanyName,
  T.N.value('(WebsiteUrl/text())[1]', 'varchar(250)') as WebsiteUrl,
  (
    select ', '+P.N.value('text()[1]', 'varchar(max)')
    from T.N.nodes('PrimaryServices,SecondaryServices') as P(N)
    for xml path(''), type
  ).value('substring(text()[1], 2)', 'varchar(max)') as Services,
  T.N.value('(Description/text())[1]', 'varchar(max)') as Description
from @XML.nodes('/root/DocInfo') as T(N)