使用T-SQL生成XML和一些问题

时间:2018-10-15 20:07:18

标签: sql xml tsql xml-namespaces

一段时间以来,我一直在使用您的知识,但是这次我没有找到问题的答案。 我是自学成才的,所以请原谅我任何错误。

我需要生成XML,但是我从未使用SQL来完成,因此存在一些问题。 我已经生成了核心,但是我需要添加架构和版本,但是我无法创建它。

我准备了一个快速示例,它必须是相同的体系结构。 现在的样子:

  <s:headers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://www.example.com">
      <warehouse_iss type="T">
        <idn>wareh</idn>
      </warehouse_iss>
      <iss_id type="T">
        <id>1</id>
      </iss_id>
      <date>2018-10-15T21:48:36.220</date>
      <items xmlns:s="http://www.example.com">
        <prod_index type="T">
          <idn>abc</idn>
        </prod_index>
        <qty>1.230000000000000e+002</qty>
        <parameters xmlns:s="http://www.example.com">
          <parameter>
            <par_id type="T">
              <id>1</id>
            </par_id>
            <par_value type="T">
              <id>abcdef</id>
            </par_value>
          </parameter>
        </parameters>
      </items>
    </s:headers>

应如何显示:

<?xml version="1.0" encoding="UTF-8"?>
<s:headers xmlns:s="http://www.example.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.com/example ../../Schema/example.xsd ">
  <warehouse_iss type="T">
    <idn>wareh</idn>
  </warehouse_iss>
  <iss_id type="T">
    <id>1</id>
  </iss_id>
  <date>2018-10-15T21:48:36.220</date>
  <items>
    <prod_index type="T">
      <idn>abc</idn>
    </prod_index>
    <qty>1.230000000000000e+002</qty>
    <parameters>
      <parameter>
        <par_id type="T">
          <id>1</id>
        </par_id>
        <par_value type="T">
          <id>abcdef</id>
        </par_value>
      </parameter>
    </parameters>
  </items>
</s:headers>

因此,我需要添加所有架构和元素,并且不应在子节点中重复它。 我还需要添加版本。

我准备帮助您的代码(MyFunction当然是将“ @type”添加到输出XML的函数) ;)

create table #temp_headers (warehouse_iss varchar(5), iss_id int, date datetime)
create table #temp_items (prod_index varchar(10), qty float)
create table #temp_parameter (par_id int,  par_value varchar(10), prod_index varchar(10))
insert into #temp_headers values ('wareh',1,getdate())
insert into #temp_items  values ('abc',123)
insert into #temp_parameter values (1, 'abcdef','abc')


WITH XMLNAMESPACES ('http://www.example.com' as s)
select 
                                dbo.MyFunction(1,'T') as "warehouse_iss/@type", 
                                warehouse_iss as "warehouse_iss/idn",
                                dbo.MyFunction(1,'T') as "iss_id/@type", 
                                iss_id as "iss_id/id", --- iss_id
                                GETDATE() date, --- date
                                    (select 
                                        dbo.MyFunction(1,'T') as "prod_index/@type", 
                                        prod_index as "prod_index/idn", 
                                        qty,
                                        (select 
                                        dbo.MyFunction(1,'T') as "par_id/@type", 
                                        par_id as "par_id/id", 
                                        dbo.MyFunction(1,'T') as "par_value/@type", 
                                        par_value as "par_value/id"
                                        from #temp_parameter para                                       
                                        where para.prod_index = items.prod_index
                                        FOR XML PATH ('parameter'), ROOT ('parameters'), type
                                        )
                                        from #temp_items items
                                        for xml path ('items'), type
                                        )
                                from #temp_headers head

                                for xml path ('s:headers'),     ELEMENTS XSINIL 

谢谢。

1 个答案:

答案 0 :(得分:0)

这是一个非常烦人的问题,已经有十年了,但是Microsoft不愿意更改它。命名空间在子查询中反复出现。搜索此内容,您将找到数百个与此相关的问题。连接问题已经有十多年了,有很多支持者,但是连接消失了,问题也消失了,但是名称空间仍然存在...

顺便说一句:您的查询很棒!

但是,解决方案是可行的,但是很难看。您必须创建不带名称空间的XML,并在字符串末尾添加它们:

create table #temp_headers (warehouse_iss varchar(5), iss_id int, date datetime)
create table #temp_items (prod_index varchar(10), qty float)
create table #temp_parameter (par_id int,  par_value varchar(10), prod_index varchar(10))
insert into #temp_headers values ('wareh',1,getdate())
insert into #temp_items  values ('abc',123)
insert into #temp_parameter values (1, 'abcdef','abc');

-测试场景!

DECLARE @intermediateXML XML=
(
    select 
        'Dummy T' as "warehouse_iss/@type", 
        warehouse_iss as "warehouse_iss/idn",
        'Dummy T' as "iss_id/@type", 
        iss_id as "iss_id/id", --- iss_id
        GETDATE() date, --- date
            (select 
                'Dummy T' as "prod_index/@type", 
                prod_index as "prod_index/idn", 
                qty,
                (select 
                'Dummy T' as "par_id/@type", 
                par_id as "par_id/id", 
                'Dummy T' as "par_value/@type", 
                par_value as "par_value/id"
                from #temp_parameter para                                       
                where para.prod_index = items.prod_index
                FOR XML PATH ('parameter'), ROOT ('parameters'), type
                )
                from #temp_items items
                for xml path ('items'), type
                )
        from #temp_headers head

        for xml path ('DummyHeaders') 
);

-将其广播到NVARCHAR(MAX) ...

DECLARE @XML_as_String NVARCHAR(MAX)=CAST(@intermediateXML AS NVARCHAR(MAX));

--...并使用字符串方法在字符串级别添加标题

DECLARE @Header NVARCHAR(MAX)=
N'<s:headers xmlns:s="http://www.example.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.com/example ../../Schema/example.xsd ">';

DECLARE @finalXML XML=
(
    REPLACE(
        (SELECT @Header + 
           (
            SELECT SUBSTRING(@XML_as_String,CHARINDEX(N'<warehouse_iss',@XML_as_String),LEN(@XML_as_String))
           )
        ),'</DummyHeaders>','</s:headers>')
);

SELECT @finalXML

GO
DROP TABLE #temp_headers
DROP TABLE #temp_items
DROP TABLE #temp_parameter

提示:关于 xml声明 <?xml blah?>

的一句话

默认情况下,您的XML编码为NVARCHAR(MAX)(即UCS-2,几乎是utf-16)。如果您添加了一个声明以告知使用者嘿,我是{{1 }}!,这不是事实,该声明不是作为XML的一部分,而是作为预先来告知消费者如何解码内容的声明。服务器甚至不允许您将其存储为本地XML。

但是-当然-您可以在字符串中添加任何字符串。因此,您可以将声明添加到强制转换的XML中(但不要将其强制转换回XML!)。如果将此内容写到光盘上的文件中,则应确保该文件实际上是utf-8编码的。否则您的文件将是骗子;-)