Home > Software engineering >  Prevent repeating Elements using For XML Path in T-SQL output
Prevent repeating Elements using For XML Path in T-SQL output

Time:08-05

I am currently working on creating XML output via SQL Server for a 3rd party application using T-SQL. I have a specification of what the XML format should like. I am just struggling to get it precisely how it needs to be. I have provided some sample data to explain what is happening.

CREATE TABLE #XML
( 
 party_id NVARCHAR(8)
,data_timestamp datetime
,active_customer bit
,code  NVARCHAR(30)
,[description] NVARCHAR(20)
,date_of_birth date
,initials_np NVARCHAR(20)
,first_name NVARCHAR(20)
,last_name NVARCHAR(20)
,address_type NVARCHAR(20)
,address NVARCHAR(40)
,city NVARCHAR(10)
 )
 INSERT INTO #XML
 (
  party_id 
,data_timestamp 
,active_customer
,code  
,[description] 
,date_of_birth 
,initials_np 
,first_name 
,last_name 
,address_type 
,address 
,city 

 )
 Values('CUST1',GETDATE(),1,'Customer Found','Valid', '11/05/1979', 'JBS','John','Smith','Primary Address','5 Cod street', 'Amsterdam')
 ,('CUST1',GETDATE(),1,'Customer Found','Valid', '11/05/1979', 'JBS','John','Smith','Secondary Address','4 Pike street', 'Rotterdam')
 ,('CUST2',GETDATE(),0,'Customer not Found',NULL, NULL, NULL,NULL,NULL,NULL,NULL, NULL)

The query I have so far is

SELECT 
data_timestamp as 'Metadata/data_timestamp'
,code as 'notification/code'
,[description] as   'notification/description'
,date_of_birth as 'register/natural_person/date_of_birth'
,initials_np as 'register/natural_person/name/Initials'
,first_name as   'register/natural_person/name/first_name'
,last_name as  'register/natural_person/name/last_name'
 ,(   SELECT 
            B.city , B.address_type ,
            B.address
            FROM  #XML AS B
            WHERE B.party_id = T.party_id
                FOR XML PATH ('address'), TYPE
            ) 
FROM #XML T
FOR XML PATH, ROOT('bdrp_client_response'), TYPE, ELEMENTS XSINIL;

This query gives me the following output:

<bdrp_client_response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
    <Metadata>
      <data_timestamp>2022-08-04T22:15:33.537</data_timestamp>
    </Metadata>
    <notification>
      <code>Customer Found</code>
      <description>Valid</description>
    </notification>
    <register>
      <natural_person>
        <date_of_birth>1979-11-05</date_of_birth>
        <name>
          <Initials>JBS</Initials>
          <first_name>John</first_name>
          <last_name>Smith</last_name>
        </name>
      </natural_person>
    </register>
    <address>
      <city>Amsterdam</city>
      <address_type>Primary Address</address_type>
      <address>5 Cod street</address>
    </address>
    <address>
      <city>Rotterdam</city>
      <address_type>Secondary Address</address_type>
      <address>4 Pike street</address>
    </address>
  </row>
  <row>
    <Metadata>
      <data_timestamp>2022-08-04T22:15:33.537</data_timestamp>
    </Metadata>
    <notification>
      <code>Customer Found</code>
      <description>Valid</description>
    </notification>
    <register>
      <natural_person>
        <date_of_birth>1979-11-05</date_of_birth>
        <name>
          <Initials>JBS</Initials>
          <first_name>John</first_name>
          <last_name>Smith</last_name>
        </name>
      </natural_person>
    </register>
    <address>
      <city>Amsterdam</city>
      <address_type>Primary Address</address_type>
      <address>5 Cod street</address>
    </address>
    <address>
      <city>Rotterdam</city>
      <address_type>Secondary Address</address_type>
      <address>4 Pike street</address>
    </address>
  </row>
  <row>
    <Metadata>
      <data_timestamp>2022-08-04T22:15:33.537</data_timestamp>
    </Metadata>
    <notification>
      <code>Customer not Found</code>
      <description xsi:nil="true" />
    </notification>
    <register>
      <natural_person>
        <date_of_birth xsi:nil="true" />
        <name>
          <Initials xsi:nil="true" />
          <first_name xsi:nil="true" />
          <last_name xsi:nil="true" />
        </name>
      </natural_person>
    </register>
    <address />
  </row>
</bdrp_client_response>

The actual response I need is:

<bdrp_client_response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Metadata>
      <data_timestamp>2022-08-04T22:15:33.537</data_timestamp>
    </Metadata>
    <notification>
      <code>Customer Found</code>
      <description>Valid</description>
    </notification>
    <register>
      <natural_person>
        <date_of_birth>1979-11-05</date_of_birth>
        <name>
          <Initials>JBS</Initials>
          <first_name>John</first_name>
          <last_name>Smith</last_name>
        </name>
        <address>
            <city>Amsterdam</city>
            <address_type>Primary Address</address_type>
            <address>5 Cod street</address>
        </address>
        <address>
            <city>Rotterdam</city>
            <address_type>Secondary Address</address_type>
            <address>4 Pike street</address>
        </address>
        </natural_person>
    </register>
    <Metadata>
      <data_timestamp>2022-08-04T22:15:33.537</data_timestamp>
    </Metadata>
    <notification>
      <code>Customer not Found</code>
      <description xsi:nil="true" />
    </notification>
    <register>
      <natural_person xsi:nil="true" />
    </register>
 </bdrp_client_response>

For the data, my code appears to be repeating elements based on the 2 rows for the same customer. The only elements that should be repeated are addresses as customers can have multiple addresses. The other elements (notification and metadata) should only appear once per customer. In the case of the second customer in the sample data, as there are no customer details the address and name elements should not be seen. Only <natural_person xsi:nil="true" />.

Additionally, how can I get rid of the <row></row> elements? Any help would be much appreciated

CodePudding user response:

Please try the following.

SQL

DECLARE @tbl TABLE ( 
     party_id NVARCHAR(8)
    ,data_timestamp datetime
    ,active_customer bit
    ,code  NVARCHAR(30)
    ,[description] NVARCHAR(20)
    ,date_of_birth date
    ,initials_np NVARCHAR(20)
    ,first_name NVARCHAR(20)
    ,last_name NVARCHAR(20)
    ,address_type NVARCHAR(20)
    ,address NVARCHAR(40)
    ,city NVARCHAR(10)
 );
 INSERT INTO @tbl
 (
      party_id 
    ,data_timestamp 
    ,active_customer
    ,code  
    ,[description] 
    ,date_of_birth 
    ,initials_np 
    ,first_name 
    ,last_name 
    ,address_type 
    ,address 
    ,city 
 )
VALUES
('CUST1',GETDATE(),1,'Customer Found','Valid', '11/05/1979', 'JBS','John','Smith','Primary Address','5 Cod street', 'Amsterdam'),
('CUST1',GETDATE(),1,'Customer Found','Valid', '11/05/1979', 'JBS','John','Smith','Secondary Address','4 Pike street', 'Rotterdam'),
('CUST2',GETDATE(),0,'Customer not Found',NULL, NULL, NULL,NULL,NULL,NULL,NULL, NULL);

;WITH rs AS
(
    SELECT party_id, data_timestamp 
        ,active_customer
        ,code  
        ,[description] 
        ,date_of_birth 
        ,initials_np 
        ,first_name 
        ,last_name 
    FROM @tbl
    GROUP BY party_id, data_timestamp 
        ,active_customer
        ,code  
        ,[description] 
        ,date_of_birth 
        ,initials_np 
        ,first_name 
        ,last_name 
)
SELECT data_timestamp as 'Metadata/data_timestamp'
    ,code as 'notification/code'
    ,[description] as   'notification/description'
    ,date_of_birth as 'register/natural_person/date_of_birth'
    ,initials_np as 'register/natural_person/name/Initials'
    ,first_name as   'register/natural_person/name/first_name'
    ,last_name as  'register/natural_person/name/last_name'
     ,(SELECT B.city, B.address_type ,
            B.address
            FROM  @tbl AS B
            WHERE B.party_id = T.party_id
            FOR XML PATH ('address'), TYPE
    ) 
FROM rs AS t
FOR XML PATH(''), ROOT('bdrp_client_response'), TYPE, ELEMENTS XSINIL;
  • Related