用变量替换XML节点元素

时间:2016-12-23 20:31:26

标签: sql-server xml sql-server-2008 xquery

我目前有以下代码在名为PARTY的父节点下创建XML。 PARTY节点内部是另一个名为ROLE的节点。我的问题是如何用xquery中的[SequenceNr]变量替换当前的ROLE节点,该节点只是说ROLE。

我曾尝试在@OutputXml中进行替换但是没有用,我认为在xquery中应该有一个我不知道的简单方法。

当前代码:

WITH [PartyNodes] AS
        (
            SELECT  (   
                        SELECT  [dbo].[XmlA](@Id),
                                [dbo].[XmlB](@Id)
                        FOR XML PATH(''),TYPE
                    ) AS [AllTogether]
        )
        ,[NumberedSequences] AS
        (
            SELECT  'PARTY' + CONVERT(NVARCHAR, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + 10) + '_ROLE1' AS [PartySequenceNr], -- party label
                    ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + 10 AS [SequenceNr], -- party sequence
                    [T].[Party].[query]('.') AS [TheNode]
            FROM [PartyNodes]
            CROSS APPLY [AllTogether].[nodes]('/PARTY') AS T(Party)
        )
        SELECT @OutputXml = (   SELECT [TheNode].[query]('let $p:=/PARTY[1]
                                                      let $lbl:=sql:column("PartySequenceNr")
                                                      let $nr:=sql:column("SequenceNr")
                                                      return
                                                     <PARTY SequenceNumber="{$nr}" xlink_label="{$lbl}" >
                                                     {$p/*}
                                                    </PARTY>'
                                                )
                                FROM [NumberedSequences]
                                FOR XML PATH(''),ROOT('PARTIES')
                                );

当前输出:

<PARTY SequenceNumber="1" xlink:label="PARTY1_ROLE1">
    <INDIVIDUAL>
      <NAME>
         <FullName>Test</FullName>
       </NAME>
    </INDIVIDUAL>
    <ROLES>
       <ROLE>
            <A>Test</A>
       </ROLE>
    </ROLES>
</PARTY>

期望的输出:

<PARTY SequenceNumber="1" xlink:label="PARTY1_ROLE1">
    <INDIVIDUAL>
      <NAME>
         <FullName>Test</FullName>
       </NAME>
    </INDIVIDUAL>
    <ROLES>
       <ROLE SequenceNumber="1" xlink:label="PARTY1_ROLE1">>
            <A>Test</A>
       </ROLE>
    </ROLES>
</PARTY>

1 个答案:

答案 0 :(得分:2)

我试图跟随你的想法,但不能......

有两个函数XmlAXmlB。首先,将结果合并到AllTogether。稍后您使用.nodes('/PARTY')来读取此内容,但您显示的XML只有一个PARTY节点作为root。

您还可以使用FLWOR-XQuery 插入这两个属性。但我怀疑,xlink_label会显示为xlink:label

您展示的XML不能是上述结果......或者我遗漏了某些东西......

我的第一个想法是:这似乎过于复杂......如果以下内容无效,请提供有关目标的更多详细信息,请尝试set up a MCVE。这可能是the XY-problem

我从没有属性的XML开始,假设这是前面的结果:

DECLARE @xml XML=
N'<PARTY>
    <INDIVIDUAL>
      <NAME>
         <FullName>Test</FullName>
       </NAME>
    </INDIVIDUAL>
    <ROLES>
       <ROLE>
            <A>Test</A>
       </ROLE>
    </ROLES>
</PARTY>';

- 此查询会在PARTYROLE

中插入属性
DECLARE @PartySequenceNr INT = 1;
DECLARE @SequenceNr VARCHAR(100)='PARTY1_ROLE1';

SELECT @xml.query
(N' 
    let $p:=/PARTY[1]
    let $lbl:=sql:variable("@PartySequenceNr")
    let $nr:=sql:variable("@SequenceNr")
    return
    <PARTY SequenceNumber="{$nr}" xlink_label="{$lbl}" >
    {
        for $nd in $p/*
        return
            if(local-name($nd)="ROLES") then
            ( 
                <ROLES><ROLE SequenceNumber="{$nr}" xlink_label="{$lbl}" >
                {$nd/ROLE/*}
                </ROLE></ROLES>
            )
            else $nd
    }
    </PARTY>
') 

结果:

<PARTY SequenceNumber="PARTY1_ROLE1" xlink_label="1">
  <INDIVIDUAL>
    <NAME>
      <FullName>Test</FullName>
    </NAME>
  </INDIVIDUAL>
  <ROLES>
    <ROLE SequenceNumber="PARTY1_ROLE1" xlink_label="1">
      <A>Test</A>
    </ROLE>
  </ROLES>
</PARTY>

使用名称空间xlink

如果您需要命名空间

,请使用此选项
SELECT @xml.query
(N' declare namespace xlink="DummyUrl";
    let $p:=/PARTY[1]
    let $lbl:=sql:variable("@PartySequenceNr")
    let $nr:=sql:variable("@SequenceNr")
    return
    <PARTY SequenceNumber="{$nr}" xlink:label="{$lbl}" >
    {
    for $nd in $p/*
    return
        if(local-name($nd)="ROLES") then
        ( 
            <ROLES><ROLE SequenceNumber="{$nr}" xlink:label="{$lbl}" >

            {$nd/ROLE/*}

            </ROLE></ROLES>
        )
        else $nd
    }
    </PARTY>
')

结果

<PARTY SequenceNumber="PARTY1_ROLE1" xmlns:xlink="DummyUrl" xlink:label="1">
  <INDIVIDUAL>
    <NAME>
      <FullName>Test</FullName>
    </NAME>
  </INDIVIDUAL>
  <ROLES>
    <ROLE SequenceNumber="PARTY1_ROLE1" xlink:label="1">
      <A>Test</A>
    </ROLE>
  </ROLES>
</PARTY>