从父节点 xml sql server 检索所有子节点

2021-10-01 00:00:00 xml sql sql-server

我有这个 xml:

<viewNode xsi:type="View:Projection" name="Projection_1">
<endUserTexts label=" "/>
<element name="CITY">
  <inlineType primitiveType="CHAR" length="0" precision="0" scale="0"/>
</element>
<element name="ROAD_ID">
  <inlineType primitiveType="CHAR" length="0" precision="0" scale="0"/>
</element>
<element name="LEN">
  <inlineType primitiveType="CHAR" length="0" precision="0" scale="0"/>
</element>
<element name="CITY2">
  <inlineType primitiveType="CHAR" length="0" precision="0" scale="0"/>
</element>
<element name="F">
  <inlineType name="INTEGER" primitiveType="INTEGER" length="0" precision="0" scale="0"/>
</element>
<elementFilter elementName="F">
  <valueFilter xsi:type="Column:SingleValueFilter" including="true" value="1"/>
</elementFilter>
<input>
  <viewNode xsi:type="View:JoinNode">#/0/Join_1</viewNode>
  <mapping xsi:type="Type:ElementMapping" targetName="CITY" sourceName="CITY"/>
  <mapping xsi:type="Type:ElementMapping" targetName="ROAD_ID" sourceName="ROAD_ID"/>
  <mapping xsi:type="Type:ElementMapping" targetName="LEN" sourceName="LEN"/>
  <mapping xsi:type="Type:ElementMapping" targetName="CITY2" sourceName="CITY2"/>
  <mapping xsi:type="Type:ElementMapping" targetName="F" sourceName="F"/>
</input></viewNode>

这是我检索数据的代码:

and this is my code to retrieve the data:

SELECT 
Tab.Col.value('../@name','nvarchar(50)') as ViewNode,
Tab.Col.value('@name','nvarchar(50)') as Name,
Tab.Col.value('(endUserTexts/@label)[1]','nvarchar(50)') as Label,  
Tab.Col.value('(inlineType/@primitiveType)[1]','nvarchar(50)') as PrimitveType, 
Tab.Col.value('(inlineType/@length)[1]','nvarchar(50)') as Length,  
Tab.Col.value('(inlineType/@precision)[1]','nvarchar(50)') as Precision,    
Tab.Col.value('(inlineType/@scale)[1]','nvarchar(50)') as Scale 
FROM @x.nodes('/viewNode/element') AS Tab(Col)

这种方式有效并检索每个元素的数据,但我还想从 elementFilter 检索数据,并将其视为另一个元素.我的问题是,有没有办法检索父节点 viewNode 的所有子节点?

This way works and retrieves the data for each element, but I would like to also retrieve the data from elementFilter, and treat it as if it were another element. My question is, there is a way to retrieve all the child nodes of the parent node viewNode?

类似于FROM @x.nodes('/viewNode/ANYCHILDNODE') AS Tab(Col)

推荐答案

首先:提供的示例不完整,因为缺少命名空间 xsi 的声明.在我的示例中,我添加了一个虚拟声明...

First of all: The provided example cannot be complete as there is a declaration for the namespace xsi missing. In my example I've added a dummy declaration...

这种方式有效并检索每个元素的数据,但我会还喜欢从 elementFilter 中检索数据,并将其视为如果它是另一个元素.我的问题是,有一种方法可以检索父节点viewNode的所有子节点?就像是FROM @x.nodes('/viewNode/ANYCHILDNODE') AS Tab(Col)

This way works and retrieves the data for each element, but I would like to also retrieve the data from elementFilter, and treat it as if it were another element. My question is, there is a way to retrieve all the child nodes of the parent node viewNode? Something like FROM @x.nodes('/viewNode/ANYCHILDNODE') AS Tab(Col)

在这种情况下,最好提供预期的输出...

In such cases it was best to provide the expected output...

不共享相同的属性.而 完全是另一回事,包括与 1:n 相关的 数组本身...

<element> and <elementFilter> do not share the same attributes. And <input> is something else entirely, including a 1:n related <mapping> array itself...

所以:是的,有 * 的意思是 ANYCHILD.像 /viewNode/* 这样的 XPath 将返回 下的所有子节点.然后,您可以使用 local-name() 对元素的名称做出正常的反应.在下面的代码中,我向 XPath 添加了一个 substring predicate 以返回以短语 element 开头的元素.这将返回 但将忽略 .试试看:

So: Yes, there is * meaning ANYCHILD. An XPath like /viewNode/* will return all children below <viewNode>. You can then use local-name() to react on an element's name gerically. In the following clode I add a substring predicate to the XPath in order to return elements starting with the phrase element. This will return <element> and <elementFilter> but will ignore <input>. Try it out:

DECLARE @x XML=
N'<viewNode xmlns:xsi="dummy" xsi:type="View:Projection" name="Projection_1">
  <endUserTexts label=" " />
  <element name="CITY">
    <inlineType primitiveType="CHAR" length="0" precision="0" scale="0" />
  </element>
  <element name="ROAD_ID">
    <inlineType primitiveType="CHAR" length="0" precision="0" scale="0" />
  </element>
  <element name="LEN">
    <inlineType primitiveType="CHAR" length="0" precision="0" scale="0" />
  </element>
  <element name="CITY2">
    <inlineType primitiveType="CHAR" length="0" precision="0" scale="0" />
  </element>
  <element name="F">
    <inlineType name="INTEGER" primitiveType="INTEGER" length="0" precision="0" scale="0" />
  </element>
  <elementFilter elementName="F">
    <valueFilter xsi:type="Column:SingleValueFilter" including="true" value="1" />
  </elementFilter>
  <input>
    <viewNode xsi:type="View:JoinNode">#/0/Join_1</viewNode>
    <mapping xsi:type="Type:ElementMapping" targetName="CITY" sourceName="CITY" />
    <mapping xsi:type="Type:ElementMapping" targetName="ROAD_ID" sourceName="ROAD_ID" />
    <mapping xsi:type="Type:ElementMapping" targetName="LEN" sourceName="LEN" />
    <mapping xsi:type="Type:ElementMapping" targetName="CITY2" sourceName="CITY2" />
    <mapping xsi:type="Type:ElementMapping" targetName="F" sourceName="F" />
  </input>
</viewNode>';

--注意命名空间...

--Beware of the namespace...

WITH XMLNAMESPACES('dummy' AS xsi)
SELECT 
Tab.Col.value('../@name','nvarchar(50)') as ViewNode,
Tab.Col.value('@name','nvarchar(50)') as Name,
Tab.Col.value('(endUserTexts/@label)[1]','nvarchar(50)') as Label,  
Tab.Col.value('(inlineType/@primitiveType)[1]','nvarchar(50)') as PrimitveType, 
Tab.Col.value('(inlineType/@length)[1]','nvarchar(50)') as Length,  
Tab.Col.value('(inlineType/@precision)[1]','nvarchar(50)') as Precision,    
Tab.Col.value('(inlineType/@scale)[1]','nvarchar(50)') as Scale,
Tab.Col.value('@elementName','nvarchar(50)') as filter_elementName,
Tab.Col.value('(valueFilter/@xsi:type)[1]','nvarchar(50)') as filter_ValueFilterType,
Tab.Col.value('(valueFilter/@including)[1]','bit') as filter_Including,
Tab.Col.value('(valueFilter/@value)[1]','nvarchar(50)') as filter_value
FROM @x.nodes('/viewNode/*[substring(local-name(),1,7)="element"]') AS Tab(Col)

相关文章