从 SQL 获取多个 XML 值

Getting multiple XML values from SQL

我有一个名为 'views' 的 table,其中包含从 Microsoft Service Manager 数据库中提取的数据。为了简化这个问题,我会说这个 table 有 2 列:

Views
----------
ViewId    (uniqueidentifier)
ConfigXML (xml)

XML 数据示例如下:

<Data>
  <Adapters>
    <Adapter AdapterName="dataportal:EnterpriseManagementObjectProjectionAdapter">
      <AdapterAssembly>Microsoft.EnterpriseManagement.UI.SdkDataAccess</AdapterAssembly>
      <AdapterType>Microsoft.EnterpriseManagement.UI.SdkDataAccess.DataAdapters.EnterpriseManagementObjectProjectionAdapter</AdapterType>
    </Adapter>
    <Adapter AdapterName="viewframework://Adapters/AdvancedList">
      <AdapterAssembly>Microsoft.EnterpriseManagement.UI.ViewFramework</AdapterAssembly>
      <AdapterType>Microsoft.EnterpriseManagement.UI.ViewFramework.AdvancedListSupportAdapter</AdapterType>
    </Adapter>
    <Adapter AdapterName="omsdk://Adapters/Criteria">
      <AdapterAssembly>Microsoft.EnterpriseManagement.UI.SdkDataAccess</AdapterAssembly>
      <AdapterType>Microsoft.EnterpriseManagement.UI.SdkDataAccess.DataAdapters.SdkCriteriaAdapter</AdapterType>
    </Adapter>
  </Adapters>
  <ItemsSource>
    <AdvancedListSupportClass xmlns="clr-namespace:Microsoft.EnterpriseManagement.UI.ViewFramework;assembly=Microsoft.EnterpriseManagement.UI.ViewFramework" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" DataTypeName="" AdapterName="viewframework://Adapters/AdvancedList" FullUpdateAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter" DataSource="mom:ManagementGroup" FullUpdateFrequency="100" Streaming="true" IsRecurring="true" RecurrenceFrequency="{x:Static s:Int32.MaxValue}" UpdateItemsAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter" AppendItemsAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter" RemoveItemsAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter">
      <AdvancedListSupportClass.Parameters>
        <QueryParameter Parameter="TypeProjectionId" Value="$MPElement[Name='IncidentManagement!System.WorkItem.Incident.ProjectionType']$" />
      </AdvancedListSupportClass.Parameters>
    </AdvancedListSupportClass>
  </ItemsSource>
  <Criteria>
    <QueryCriteria xmlns="http://tempuri.org/Criteria.xsd" Adapter="omsdk://Adapters/Criteria">
      <Criteria>
        <FreeformCriteria>
          <Freeform>
            <Criteria xmlns="http://Microsoft.EnterpriseManagement.Core.Criteria/">
              <Expression>
                <And>
                  <Expression>
                    <Or>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type='CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident']/Status$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{5e2d3932-ca6d-1515-7310-6f58584df73e}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type='CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident']/Status$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{b6679968-e84e-96fa-1fec-8cd4ab39c3de}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
                    </Or>
                  </Expression>
                  <Expression>
                    <Or>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type='CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident']/TierQueue$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{e41fea6c-90fa-4c6d-48fb-6d90ef3e8348}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type='CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident']/TierQueue$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{bfe405d7-11f3-09cc-882f-709b5505849d}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
...

我尤其对 'Expression' 节点感兴趣。我试图从 Expression/SimpleExpression/ValueExpressionLeft/Value 中提取值,但仅在 Expression/SimpleExpression/ValueExpressionRight/Property 包含文本 'TierQueue'.

的地方

与此匹配的表达式节点数量各不相同。一些 ConfigXML 值只有一个条目匹配,其他的最多有 10 个条目。我需要所有匹配项。

最后的 table 应该是这样的:

ViewID                                  TierQueue
----------------                        -----------------
3CC97021-1C04-64BB-6391-00A48C07AB41    20ad0c6e-a41d-aab9-cc16-ae6e5efe45d8
08EA4E4C-ED4B-7E56-E257-04717A7289E8    e3d37f4a-3ccd-1abd-3180-9b439616ce43
1502A994-5A82-E6C9-E278-05569CC929C9    0fa5f999-4d19-3a72-a0c4-ff48db2bfdd8
1502A994-5A82-E6C9-E278-05569CC929C9    666d6236-0deb-4c8f-0922-9e44245d692e
F0301A91-C6B6-E332-7F82-06DC59352D93    dbff58a6-d7f0-4b15-33d4-e2b0edbd6fe8
F0301A91-C6B6-E332-7F82-06DC59352D93    f9ba3c86-d6f5-f91d-98aa-10db1f9d054d

到目前为止我做了什么

我承认,我以前从未与 XML 合作过,所以我尝试过的只是尝试从网上的示例中拼凑一些东西。

据我所知:

SELECT
ViewID,
n.p.value('(//*[local-name()="Value"]/text())[1]', 'nvarchar(max)') as TierQueueID
FROM views smv
CROSS APPLY smv.ConfigurationXML.nodes('(//*[local-name()="SimpleExpression"])') as n (p)

不幸的是,这给了我错误的结果。它只是在每个 XML 文档中第一次出现 'Value',然后将其复制几次

灵感来源:

declare @x xml = N'
<Data>
  <Adapters>
    <Adapter AdapterName="dataportal:EnterpriseManagementObjectProjectionAdapter">
      <AdapterAssembly>Microsoft.EnterpriseManagement.UI.SdkDataAccess</AdapterAssembly>
      <AdapterType>Microsoft.EnterpriseManagement.UI.SdkDataAccess.DataAdapters.EnterpriseManagementObjectProjectionAdapter</AdapterType>
    </Adapter>
    <Adapter AdapterName="viewframework://Adapters/AdvancedList">
      <AdapterAssembly>Microsoft.EnterpriseManagement.UI.ViewFramework</AdapterAssembly>
      <AdapterType>Microsoft.EnterpriseManagement.UI.ViewFramework.AdvancedListSupportAdapter</AdapterType>
    </Adapter>
    <Adapter AdapterName="omsdk://Adapters/Criteria">
      <AdapterAssembly>Microsoft.EnterpriseManagement.UI.SdkDataAccess</AdapterAssembly>
      <AdapterType>Microsoft.EnterpriseManagement.UI.SdkDataAccess.DataAdapters.SdkCriteriaAdapter</AdapterType>
    </Adapter>
  </Adapters>
  <ItemsSource>
    <AdvancedListSupportClass xmlns="clr-namespace:Microsoft.EnterpriseManagement.UI.ViewFramework;assembly=Microsoft.EnterpriseManagement.UI.ViewFramework" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" DataTypeName="" AdapterName="viewframework://Adapters/AdvancedList" FullUpdateAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter" DataSource="mom:ManagementGroup" FullUpdateFrequency="100" Streaming="true" IsRecurring="true" RecurrenceFrequency="{x:Static s:Int32.MaxValue}" UpdateItemsAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter" AppendItemsAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter" RemoveItemsAdapter="dataportal:EnterpriseManagementObjectProjectionAdapter">
      <AdvancedListSupportClass.Parameters>
        <QueryParameter Parameter="TypeProjectionId" Value="$MPElement[Name=''IncidentManagement!System.WorkItem.Incident.ProjectionType'']$" />
      </AdvancedListSupportClass.Parameters>
    </AdvancedListSupportClass>
  </ItemsSource>

    <Criteria>
    <QueryCriteria xmlns="http://tempuri.org/Criteria.xsd" Adapter="omsdk://Adapters/Criteria">
      <Criteria>
        <FreeformCriteria>
          <Freeform>
            <Criteria xmlns="http://Microsoft.EnterpriseManagement.Core.Criteria/">
              <Expression>
                <And>
                  <Expression>
                    <Or>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type=''CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident'']/Status$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{5e2d3932-ca6d-1515-7310-6f58584df73e}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type=''CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident'']/Status$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{b6679968-e84e-96fa-1fec-8cd4ab39c3de}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
                    </Or>
                  </Expression>
                  <Expression>
                    <Or>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type=''CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident'']/TierQueue$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{e41fea6c-90fa-4c6d-48fb-6d90ef3e8348}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
                      <Expression>
                        <SimpleExpression>
                          <ValueExpressionLeft>
                            <Property>$Context/Property[Type=''CustomSystem_WorkItem_Incident_Library!System.WorkItem.Incident'']/TierQueue$</Property>
                          </ValueExpressionLeft>
                          <Operator>Equal</Operator>
                          <ValueExpressionRight>
                            <Value>{bfe405d7-11f3-09cc-882f-709b5505849d}</Value>
                          </ValueExpressionRight>
                        </SimpleExpression>
                      </Expression>
                    </Or>
                  </Expression>
                </And>
              </Expression>
            </Criteria>
            </Freeform>
            </FreeformCriteria>
           </Criteria>
        </QueryCriteria>
       </Criteria>
</Data>
';

declare @views table(viewid int, ConfigurationXML xml);

insert into @views(viewid, ConfigurationXML)
values (1, @x);
--------------------------------------------------------------

SELECT
ViewID,
n.p.value('local-name(.)', 'varchar(50)') as nodename,
n.p.value('declare default element namespace "http://Microsoft.EnterpriseManagement.Core.Criteria/"; (ValueExpressionRight/Value)[1]', 'nvarchar(max)') as TierQueueID
FROM @views smv
CROSS APPLY smv.ConfigurationXML.nodes('
declare default element namespace "http://Microsoft.EnterpriseManagement.Core.Criteria/";
//SimpleExpression[contains((ValueExpressionLeft/Property/text())[1], "TierQueue")]') as n (p);


WITH XMLNAMESPACES (DEFAULT 'http://Microsoft.EnterpriseManagement.Core.Criteria/')  
SELECT
ViewID,
n.p.value('local-name(.)', 'varchar(50)') as nodename,
n.p.value('(ValueExpressionRight/Value)[1]', 'nvarchar(max)') as TierQueueID
FROM @views smv
CROSS APPLY smv.ConfigurationXML.nodes('//SimpleExpression[ValueExpressionLeft/Property[contains(text()[1], "TierQueue")]]') as n (p);