TSQL xQuery如何获取root / document节点

时间:2015-04-14 21:03:52

标签: sql-server xml xpath xquery

我有一个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节点的直接子节点

3 个答案:

答案 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}}

SQL Fiddle

答案 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节点,还需要一个额外的查询。