我有一个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>
数据库表中有数千行,每行都有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 /名称?包含匹配标记的元素的路径可以通过1-n级控制节点,因此使用Xpath语句将不起作用。 TabCtrl将以各种方式成为Form节点的直接子节点
答案 0 :(得分:1)
可能的解决方案:
从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
上述轴之间的差异:
ancestor::element_name
:将一个级别转到特定父级元素
..
:将一个或多个级别转到特定的祖先元素
{{1}}:使用任意名称将一个级别转到父元素
答案 1 :(得分:1)
使用nodes()在Form/TabCtrl
上粉碎XML,使用exist()检查每个碎片节点是否存在Tag=34
,最后从Form/TabCtrl/Name
获取值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
value()函数。
{{1}}
答案 2 :(得分:0)
对于任何具有控制节点的TabCtrl,此查询将返回TabCtrl/Name
,该节点具有= 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节点,还需要一个额外的查询。