如何查询所有子节点的特定属性

时间:2016-08-29 16:36:35

标签: sql sql-server xml tsql

我有以下几种xml结构:

<ObjectTemplate>
 <Sections>
   <Section Name="something" Identifier="something">
     <Options>
       <Choice text="something">
         <TextField visibility="private">

虽然并不总是如上所述。它可以是Section:

下的直接字段
<ObjectTemplate>
     <Sections>
       <Section Name="something" Identifier="something">
          <TextField visiblity="private">

有没有办法让我查询节点的所有子节点的属性&#34; visibility&#34;?

到目前为止,我有以下工作代码只是从xml中提取Section:

select distinct identifier from (
select 
T.C.value('@Name', 'nvarchar(max)') as name,
T.C.value('@Identifier', 'nvarchar(50)') as identifier

from @templatexml tx
cross apply tx.CurrentTemplateXml.nodes('(ObjectTemplate/Sections/Section)') as T(C)
) as temp

3 个答案:

答案 0 :(得分:0)

您还可以cross apply更深层次。这样的事情。

select distinct identifier from (
select 
T.C.value('@Name', 'nvarchar(max)') as name,
T.C.value('@Identifier', 'nvarchar(50)') as identifier,
V.x.value('@visibility', 'nvarchar(50)') as visibility

from @templatexml tx
cross apply tx.CurrentTemplateXml.nodes('(ObjectTemplate/Sections/Section)') as T(C)
cross apply T.C.nodes('//*[@visibility]') as V(x) -- Correction thnx @Shnugo
) as temp

答案 1 :(得分:0)

我不完全明白你想要什么,但你可能会尝试这样的事情:

DECLARE @tbl TABLE(ID INT IDENTITY,xmlColumn XML);
INSERT INTO @tbl VALUES
('<ObjectTemplate>
  <Sections>
    <Section Name="something1" Identifier="ident1">
      <Options>
        <Choice text="something">
          <TextField visibility="private" />
        </Choice>
      </Options>
    </Section>
  </Sections>
</ObjectTemplate>')
,('<ObjectTemplate>
  <Sections>
    <Section Name="something2" Identifier="ident2">
      <TextField visibility="private" />
    </Section>
  </Sections>
</ObjectTemplate>');

SELECT tbl.ID
      ,Sec.value('@Name','varchar(max)') AS SectionName
      ,Sec.value('@Identifier','varchar(max)') AS SectionIdentifier
      ,att.value('local-name(../..)','varchar(max)') AS ParentParentNode
      ,att.value('local-name(..)','varchar(max)') AS ParentNode
      ,att.value('local-name(.)','nvarchar(max)') AS AttributeName
      ,att.value('.','nvarchar(max)') AS AttributValue
FROM @tbl AS tbl
CROSS APPLY tbl.xmlColumn.nodes('/ObjectTemplate/Sections/Section') AS A(Sec)
CROSS APPLY Sec.nodes('//*') AS B(Nd)
CROSS APPLY Nd.nodes('attribute::*[local-name()="visibility"]') AS C(att)

结果

1   something1  ident1  Choice  TextField   visibility  private
2   something2  ident2  Section TextField   visibility  private

答案 2 :(得分:0)

如果您不关心/TextField个节点所在的位置,这里有一个非常简单的解决方案:

declare @t table(
    Id int identity(1,1) primary key,
    XMLData xml not null
);

insert into @t (XMLData)
values
('<ObjectTemplate>
  <Sections>
    <Section Name="something1" Identifier="ident1">
      <Options>
        <Choice text="something">
          <TextField visibility="private" />
        </Choice>
      </Options>
    </Section>
  </Sections>
</ObjectTemplate>')
,('<ObjectTemplate>
  <Sections>
    <Section Name="something2" Identifier="ident2">
      <TextField visibility="public" />
      <TextField visibility="friend" />
    </Section>
  </Sections>
</ObjectTemplate>');

select t.Id,
    s.c.query('.') as [TextField],
    s.c.value('./@visibility', 'varchar(100)') as [Visibility]
from @t t
    cross apply t.XMLData.nodes('//TextField[@visibility]') s(c);