TSQL xQuery 如何获取 root/document 节点
TSQL xQuery how to I get the root/document node
我有一个 XML 字段,其中包含类似于 .Net 在表单中构建控件的方式的数据。假设您有一个 windows 表单,您可以向表单添加多个控件,它们显示在 .Controls 属性 下。一些控件本身也可以有面板,分组框等控件。类似于下面xml中显示的内容。
<Form>
<Name>MyForm</Name>
<TabCtrl>
<Name>Tab1</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox</Name>
<Location>3,10</Location>
<Tag>34</Tag>
</TextboxCtrl>
<Label>
<Name>MyLabel</Name>
<Location>23,3</Location>
<Tag>19</Tag>>
</Label>
<Panel>
<Name>myPanel</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox2</Name>
<Location>36,210</Location>
<Tag>34</Tag>
</TextboxCtrl>
</Controls>
</Panel>
</Controls>
</TabCtrl>
<TabCtrl>
<Name>Tab2</Name>
<Controls>
...
</Controls>
</TabCtrl>
DB table 中有数千行,每行 xml 本身有时由 1000 个“控件”组成。当 TabCtrl 包含标签为 34 的控件时,我正在寻找一种查询 TabCtrl/Name 节点的方法。
我可以使用 xPath
通过此查询限制行
Select theXML from ViewTable where theXML.exist('//Tag[.="34"]') = 1
此外,我可以获得控件的名称而不是整个 xml:
Select theXML.query('//*[Tag="34"]/Label/text()') as 'Control Name'from ViewTable where theXML.exist('//Tag[.="34"]') = 1
如何获得 TabCtrl/Name?包含匹配 Tag 的元素的路径可以通过 1-n 级的 Controls 节点,因此使用 Xpath 语句将不起作用。 TabCtrl 将始终是 Form 节点的直接子节点
此查询将 return TabCtrl/Name
具有 Controls 节点的任何 TabCtrl 的 Grand child Tag =s 34:
DECLARE @theXML XML = '<Form>
<Name>MyForm</Name>
<TabCtrl>
<Name>Tab1</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox</Name>
<Location>3,10</Location>
<Tag>34</Tag>
</TextboxCtrl>
<Label>
<Name>MyLabel</Name>
<Location>23,3</Location>
<Tag>19</Tag>>
</Label>
<Panel>
<Name>myPanel</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox2</Name>
<Location>36,210</Location>
<Tag>34</Tag>
</TextboxCtrl>
</Controls>
</Panel>
</Controls>
</TabCtrl>
<TabCtrl>
<Name>Tab2</Name>
<Controls>
...
</Controls>
</TabCtrl>
</Form>'
Select @theXML.query('//TabCtrl/Controls/*[Tag="34"]/../../Name') as 'Control Name'
输出:
<Name>Tab1</Name>
我不能 100% 确定这就是您要查找的内容,但这可能是您要在此处遵循的一般模式,如果您需要获得更深层嵌套的 Tag=34 节点,则可以使用附加查询。
可能的解决方案:
从 TabCtrl/Name
获取文本的一种可能方法,其中包含一个标签为 34 的控件:
Select theXML.query('//TabCtrl[Controls/*/Tag="34"]/Name/text()') as 'Control Name'
或者,如果您需要从它的后代开始到达 <TabCtrl>
,那么您总是可以使用 parent::element_name
或 ancestor::element_name
或 ..
爬上树:
Select theXML.query('//*[Tag="34"]/ancestor::TabCtrl/Name/text()') as 'Control Name'
上面提到的轴之间的差异:
parent::element_name
: 转到 one 级别到 specific 父元素
ancestor::element_name
:进入一个或多个级别直到特定祖先元素
..
: 转到 one 级别到具有 any name[=20 的父元素=]
使用 nodes(), check the existence of Tag=34
for each shredded node using exist() and finally get the value from Form/TabCtrl/Name
with the value() 函数在 Form/TabCtrl
上粉碎 XML。
select TC.X.value('(Name/text())[1]', 'nvarchar(100)')
from YourTable as T
cross apply T.theXML.nodes('/Form/TabCtrl') as TC(X)
where TC.X.exist('*//Tag/text()[. = "34"]') = 1
我有一个 XML 字段,其中包含类似于 .Net 在表单中构建控件的方式的数据。假设您有一个 windows 表单,您可以向表单添加多个控件,它们显示在 .Controls 属性 下。一些控件本身也可以有面板,分组框等控件。类似于下面xml中显示的内容。
<Form>
<Name>MyForm</Name>
<TabCtrl>
<Name>Tab1</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox</Name>
<Location>3,10</Location>
<Tag>34</Tag>
</TextboxCtrl>
<Label>
<Name>MyLabel</Name>
<Location>23,3</Location>
<Tag>19</Tag>>
</Label>
<Panel>
<Name>myPanel</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox2</Name>
<Location>36,210</Location>
<Tag>34</Tag>
</TextboxCtrl>
</Controls>
</Panel>
</Controls>
</TabCtrl>
<TabCtrl>
<Name>Tab2</Name>
<Controls>
...
</Controls>
</TabCtrl>
DB table 中有数千行,每行 xml 本身有时由 1000 个“控件”组成。当 TabCtrl 包含标签为 34 的控件时,我正在寻找一种查询 TabCtrl/Name 节点的方法。 我可以使用 xPath
通过此查询限制行Select theXML from ViewTable where theXML.exist('//Tag[.="34"]') = 1
此外,我可以获得控件的名称而不是整个 xml:
Select theXML.query('//*[Tag="34"]/Label/text()') as 'Control Name'from ViewTable where theXML.exist('//Tag[.="34"]') = 1
如何获得 TabCtrl/Name?包含匹配 Tag 的元素的路径可以通过 1-n 级的 Controls 节点,因此使用 Xpath 语句将不起作用。 TabCtrl 将始终是 Form 节点的直接子节点
此查询将 return TabCtrl/Name
具有 Controls 节点的任何 TabCtrl 的 Grand child Tag =s 34:
DECLARE @theXML XML = '<Form>
<Name>MyForm</Name>
<TabCtrl>
<Name>Tab1</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox</Name>
<Location>3,10</Location>
<Tag>34</Tag>
</TextboxCtrl>
<Label>
<Name>MyLabel</Name>
<Location>23,3</Location>
<Tag>19</Tag>>
</Label>
<Panel>
<Name>myPanel</Name>
<Controls>
<TextboxCtrl>
<Name>MyTextBox2</Name>
<Location>36,210</Location>
<Tag>34</Tag>
</TextboxCtrl>
</Controls>
</Panel>
</Controls>
</TabCtrl>
<TabCtrl>
<Name>Tab2</Name>
<Controls>
...
</Controls>
</TabCtrl>
</Form>'
Select @theXML.query('//TabCtrl/Controls/*[Tag="34"]/../../Name') as 'Control Name'
输出:
<Name>Tab1</Name>
我不能 100% 确定这就是您要查找的内容,但这可能是您要在此处遵循的一般模式,如果您需要获得更深层嵌套的 Tag=34 节点,则可以使用附加查询。
可能的解决方案:
从 TabCtrl/Name
获取文本的一种可能方法,其中包含一个标签为 34 的控件:
Select theXML.query('//TabCtrl[Controls/*/Tag="34"]/Name/text()') as 'Control Name'
或者,如果您需要从它的后代开始到达 <TabCtrl>
,那么您总是可以使用 parent::element_name
或 ancestor::element_name
或 ..
爬上树:
Select theXML.query('//*[Tag="34"]/ancestor::TabCtrl/Name/text()') as 'Control Name'
上面提到的轴之间的差异:
parent::element_name
: 转到 one 级别到 specific 父元素ancestor::element_name
:进入一个或多个级别直到特定祖先元素..
: 转到 one 级别到具有 any name[=20 的父元素=]
使用 nodes(), check the existence of Tag=34
for each shredded node using exist() and finally get the value from Form/TabCtrl/Name
with the value() 函数在 Form/TabCtrl
上粉碎 XML。
select TC.X.value('(Name/text())[1]', 'nvarchar(100)')
from YourTable as T
cross apply T.theXML.nodes('/Form/TabCtrl') as TC(X)
where TC.X.exist('*//Tag/text()[. = "34"]') = 1