简体   繁体   English

不使用sql:variable将节点插入XML

[英]Insert node into XML without using sql:variable

I have looked throughout the interwebs (including SO but I have probably missed it) for a way to insert a node into existing XML which is contained in a variable without first creating as XML in a variable a string of the node which I would like to insert and using "set @XMLVariable01.modify('insert sql:variable("@XMLVariable02") as ...". 我遍历了整个网络(包括SO,但我可能会错过它)寻找一种方法,可以将节点插入到包含在变量中的现有XML中,而无需先在变量中创建XML作为我想要的节点字符串插入并使用“设置@ XMLVariable01.modify('插入sql:variable(“ @ XMLVariable02”)作为...”。

From the example below I would like to get as the final result: 从下面的示例中,我想得到最终结果:

<P xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <L01>
    <A xsi:nil="true" />
    <B xsi:nil="true" />
    <C xsi:nil="true" />
  </L01>
  <L02>
    <A>2</A>
    <B xsi:nil="true" />
    <C>x</C>
  </L02>
</P>

Example: 例:

declare
    @P xml;

declare
    @A varchar,
    @B varchar,
    @C varchar;

select
    @P = (
        select
            @A as [A],
            @B as [B],
            @C as [C]
        for xml path(N'L01'), root('P'), type, elements xsinil
        );

select @P; --Initial result

select
    @A = '2',
    @B = NULL,
    @C = 'x';

--select @P = ...?

select @P; --Final result

I did the following: 我做了以下事情:

select
    @P = (
        select (
            select
                v.query('.')
            from @P.nodes('P/L01') as t (v)),
            (
            select
                @A as [A],
                @B as [B],
                @C as [C]
            for xml path(N'L02'), type, elements xsinil
            )
        for xml path(N'P'), type, elements xsinil
        );

Which comes close but I don't want the 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' anywhere other than in the initial/top line of the XML: 接近了,但是我不想在XML的开头/顶部以外的任何地方使用“ xmlns:xsi =“ http://www.w3.org/2001/XMLSchema-instance”“:

<P xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <L01>
    <A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
    <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
    <C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
  </L01>
  <L02 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <A>2</A>
    <B xsi:nil="true" />
    <C>x</C>
  </L02>
</P>

Edit (2018Dec14~1343): Based on Schnugo's helpful insight (Yes, I need/want the NULL values for the purpose of documentation that the indicated elements were accounted for but that no value was received. Also, I apologize but I am not able to fully grasp all that is being suggested in 1-5.), I have come up with the following: 编辑(2018Dec14〜1343):基于Schnugo的有用见解(是的,我需要/希望使用NULL值来记录所指出的元素但未收到任何值的文档。此外,我很抱歉但我无法为了完全掌握1-5中建议的所有内容),我提出了以下建议:

select
    @P = (      
        select
            cast(replace(replace(cast(([XML].[Value]) as nvarchar(max)), cjR.Old01, cjR.New01), cjR.Old02, cjR.New02) as xml)
        from (
            select (
                select
                    v.query('.')
                from @P.nodes(N'P/L01') as t (v)),
                (
                select
                    @A as [A],
                    @B as [B],
                    @C as [C]
                for xml path(N'L02'), type, elements xsinil
                )
            for xml path(N'P'), type, elements xsinil
            ) as [XML] ([Value])
        cross join (
            select
                Value02 as Old01,
                N'' as New01,
                quotename(Value01, N'<>') as Old02,
                quotename(Value01 + Value02, N'<>') as New02
            from (
                select
                    N'P',
                    N' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
                ) as R (Value01, Value02)
            ) as cjR
        );

It seems like such a hacky way to produce what should be such a simple operation but apparently it is not. 看起来像是一种骇人听闻的方式来产生应该如此简单的操作,但显然并非如此。 I welcome any further advice to improve on this. 我欢迎任何进一步的建议以改善此情况。

You hit various flaws of SQL Server's XML support here... 您在这里遇到了SQL Server XML支持的各种缺陷...

With nested XML there's no other way then to use sub-queries. 使用嵌套的XML,便没有其他方法可以使用子查询。 But the repeating namespaces in sub-queries are a very annoying issue. 但是子查询中重复的名称空间是一个非常烦人的问题。 The XML produced is perfeclty okay, but the repeated namespace declarations can really bloat your XML enormously. 生成的XML完全可以,但是重复的名称空间声明确实会极大地膨胀您的XML。 This is discussed (and begged for a better solution) for centuries. 讨论了几个世纪(并寻求更好的解决方案)。 There was a Connect-Ticket for more than 10 years with a lot of votes. 有十多年的Connect-Ticket,获得了很多票。 But this disappeared together with Connect. 但这与Connect一起消失了。

Do you really need NULL values to show off with xsi:nil ? 您是否真的需要NULL值才能通过xsi:nil进行展示? The default is to omit them... 默认是忽略它们...

Very often you'll see ugly workarounds 很多时候,您会看到丑陋的解决方法
All of them use a CAST to NVARCHAR(MAX) , manipulate the namespaces with string methods ( STUFF , SUBSTRING , ...) and do a re-cast to XML at the end. 它们全部使用CASTNVARCHAR(MAX) ,使用字符串方法( STUFFSUBSTRING ,...)操纵名称空间,并在最后将其重铸为XML。

  1. default namespace: Create the XML without the namespace and add the top node together with a namespace 默认名称空间:创建不带名称空间的XML,并将顶部节点与名称空间一起添加
  2. prefixed namespace: Create the XML with a namespace placeholder and - again - use string methods ( REPLACE ) to correct this ( look at this answer ) 带前缀的名称空间:使用名称空间占位符创建XML,并再次使用字符串方法( REPLACE )对此进行更正( 请看此答案
  3. Your example seems to need xsi:nil to enforce NULL values not to be omited. 您的示例似乎需要xsi:nil来强制执行NULL值,以免被忽略。 This is even worse... You can create the XML as you do it and then use string methods, to throw away the wrong declarations. 更糟糕的是...您可以在创建XML的同时创建XML,然后使用字符串方法来丢弃错误的声明。
  4. You might build the whole thing on string level via concatenaion 您可以通过串联在字符串级别构建整个对象
  5. There is FOR XML EXPLICIT . FOR XML EXPLICIT This is a weird and hard-to-learn format. 这是一种奇怪且难以学习的格式。 But it is the only approach I know to set the namespaces right the way you want them. 但这是我所知的唯一一种以所需方式正确设置名称空间的方法。

I'm sorry, but this is exactly the kind of XML SQL-Server cannot build easily... 很抱歉,但这正是XML SQL Server无法轻松构建的那种...

If you need help with one of the provided options, you might start a new question with a sepcific question on this. 如果您需要有关所提供选项之一的帮助,则可以使用一个特殊的问题来开始一个新问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM