如何遍历XML中的所有节点 - Sql 2008

时间:2011-03-14 19:01:47

标签: sql tsql sql-server-2008 xpath

如何使用T-SQL迭代XML文档中的所有节点(SQL2008)。 我需要为文档中的每个不同节点路径(元素)创建表模式。

declare @x xml='
<logins>
  <roles>
    <role name="Administrator" />
    <role name="elUser" />
    <role name="ElAdministrator"/>
    <role name="regionalManager" />
    <role name="Rep"/>
    <role name="DiscountAdministrator" />
    <role name="LoginAdmin"/>
    <groups>
      <group name="Administrators">
        <role name="Administrator"/>
        <role name="elUser" />
        <role name="ElAdministrator" />
        <role name="Rep" />
        <role name="regionalManager" />
        <role name="DiscountAdministrator" />
        <role name="LoginAdmin" />
      </group>
    </groups>
  </roles>
  <members>
    <member login="apeiris" ofgroup="Administrator"></member>
  </members>
</logins>'

编辑包括上述内容, 我正在考虑创建/维护模式的通用脚本,这意味着我手头上不知道节点。

3 个答案:

答案 0 :(得分:1)

以下代码可用于映射存储在文档中的整个xml结构和值,我们只知道其根目录的名称。

当我测试它时,它只运行了几次,之后它吸收了太多的sql资源,并且无关的事务开始受到影响。

我试图找到使用nodes()函数的方法,但只有旧OPENXML做了我需要做的事情。

然后我将其插入表变量并对其进行操作。

对于这个特定问题,可以生成动态sql以验证是否存在必要的表,并在需要时创建它们后继续进行值插入。

DECLARE @idoc INT
DECLARE @param_XML XML = 
'<root>
    <element1>hello
        <element2>1</element2>
        <element3 id="3">goodbye</element3>
    </element1>
</root>'

EXEC sys.sp_xml_preparedocument @idoc OUTPUT, @param_XML


--SELECT id, parentid, nodetype,localname, prev, [text]
SELECT *
FROM OPENXML (@idoc, '/root', 2)

-- remeber to close document to avoid memory leak
EXEC sys.sp_xml_removedocument @idoc

答案 1 :(得分:0)

如果结构仍然像您发布的那样,那么您无需担心是否添加了更多角色

试试这个:

declare @x xml='
<logins>
<roles>
<role name="Administrator" />
<role name="elUser" />
<role name="ElAdministrator"/>
<role name="regionalManager" />
<role name="Rep"/>
<role name="DiscountAdministrator" />
<role name="LoginAdmin"/>
<groups>
  <group name="Administrators">
    <role name="Administrator"/>
    <role name="elUser" />
    <role name="ElAdministrator" />
    <role name="Rep" />
    <role name="regionalManager" />
    <role name="DiscountAdministrator" />
    <role name="LoginAdmin" />
  </group>
</groups>
    <groups>
  <group name="SimpleUser">
    <role name="Administrator"/>
    <role name="elUser" />
    <role name="ElAdministrator" />
    <role name="Rep" />
    <role name="regionalManager" />
    <role name="DiscountAdministrator" />
    <role name="LoginAdmin" />
  </group>
</groups>
</roles>
<members>
<member login="apeiris" ofgroup="Administrator"></member>
</members>
</logins>'

select 
row_number() over (partition by 
t.x.value('(group/@name)[1]' , 'varchar(100)') 
order by t.x.value('(group/@name)[1]' , 'varchar(100)')) Id,
t.x.value('(group/@name)[1]' , 'varchar(100)') GroupName,
p.y.value('@name' , 'varchar(100)') RoleName
from @x.nodes('//logins/roles/role') p(y)
cross apply @x.nodes('//groups') t(x)

它提供xml中的所有角色和组

答案 2 :(得分:-1)

我很确定如果您知道哪些节点将成为表,您可以使用XPath语句...您是否有该文件的样本?

这为我提供了所有7个角色名称:

SELECT      Logins.L.query('data(@name)').value('.', 'varchar(60)') as RoleName
FROM        @x.nodes('/logins/roles/role') Logins (L)

从这里开始,您可以使用相同的想法获取所需的数据,并根据您选择的SELECT结果执行任何SQL。