Генерация XML с использованием T-SQL и некоторые проблемы - PullRequest
0 голосов
/ 15 октября 2018

Я использую ваши знания в течение некоторого времени, но на этот раз я не нашел ответа на свой вопрос.Я самоучка, поэтому прости меня за любые ошибки.

Мне нужно сгенерировать 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 голосов
/ 16 октября 2018

Это очень раздражающая проблема, известная в течение десятилетия, но 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). Если вы добавите объявление, сообщающее потребителю Привет, яutf-8! , это не правда. Это объявление не подразумевается как часть XML, а как нечто заранее , сообщающее потребителю, как декодировать контент. SQL-Serverдаже не позволит вам сохранить это как собственный XML.

Но - конечно - вы можете добавить любую строку в строку. Таким образом, вы можете добавить свое объявление в приведенный XML (но не приводите его обратнов XML!). Если вы записываете это в файл на диске, вы должны быть уверены, что этот файл действительно закодирован utf-8. В противном случае ваш fИль был бы лжецом; -)

...