Search code examples
sql-serverxmlsql-server-2014for-xml-path

SQL Server XML Path issue


I am using SQL Server to load data as xml. I am using quite few tables in actual implementation to load data.

Since it easier to reproduce adding some dummy to temporary tables as below

create table #T1(Id int, ItemName varchar(25))
create table #T2(ItemId int, ImagePath varchar(25))

Insert Into #T1
values (1, 'Item1'), (2, 'Item2')

Insert Into #T2
values (1, 'Path 1'), (1, 'Path 2'), (1, 'Path 3'),
       (2, 'Path 4'), (2, 'Path 5')

I am writing query as below (this is a simplified version to reproduce)

SELECT 
    'Some title' Title,
    (SELECT
         (SELECT * 
          FROM
              (SELECT 
                   *,
                   (SELECT TOP 2 ImagePath AS 'href'
                    FROM #T2 AS Image
                    WHERE Image.ItemId = ItinRow.Id
                    FOR XML PATH('Image'), ELEMENTS, TYPE) Images
                FROM 
                    #T1 ItinRow) AS ItinItemRow
          FOR XML PATH('Collections'), TYPE, ELEMENTS)
    FOR XML PATH(''), TYPE, ELEMENTS)                   
FROM 
    (SELECT *
     FROM #T1) ItinGroupPage
FOR XML PATH('Group'), ELEMENTS

Which produces this XML structure

 <Group>
  <Title>Some title</Title>
  <Collections>
    <Id>1</Id>
    <ItemName>Item1</ItemName>
    <Images>
      <Image>
        <href>Path 1</href>
      </Image>
      <Image>
        <href>Path 2</href>
      </Image>
    </Images>
  </Collections>
  <Collections>
    <Id>2</Id>
    <ItemName>Item2</ItemName>
    <Images>
      <Image>
        <href>Path 4</href>
      </Image>
      <Image>
        <href>Path 5</href>
      </Image>
    </Images>
  </Collections>
</Group>

My issue is with this images node. What I really want is to output something as below without Images node

 <Group>
  <Title>Some title</Title>
  <Collections>
    <Id>1</Id>
    <ItemName>Item1</ItemName>    
      <Image>
        <href>Path 1</href>
      </Image>
      <Image>
        <href>Path 2</href>
      </Image>
  </Collections>
  <Collections>
    <Id>2</Id>
    <ItemName>Item2</ItemName>
      <Image>
        <href>Path 4</href>
      </Image>
      <Image>
        <href>Path 5</href>
      </Image>
  </Collections>
</Group>

But when I try to remove it from the query I get this error:

No column name was specified for column 3 of 'Items'

Is there a way to achieve expected XML structure?


Solution

  • I believe this SQL should return what you're looking for:

    SELECT
        'Some title' AS 'Title',
        (SELECT 
             Id,
             ItemName,
             (SELECT ImagePath AS 'Image/href'
              FROM #T2
              WHERE #T2.ItemId = #T1.Id
              FOR XML PATH(''), TYPE)
          FROM 
              #T1
          FOR XML PATH('Collections'), TYPE)
    FOR XML PATH(''), ROOT('Groups')
    

    In my SQL Server 2016, I get back this XML from the sample data you've provided:

    <Groups>
      <Title>Some title</Title>
      <Collections>
        <Id>1</Id>
        <ItemName>Item1</ItemName>
        <Image>
          <href>Path 1</href>
        </Image>
        <Image>
          <href>Path 2</href>
        </Image>
        <Image>
          <href>Path 3</href>
        </Image>
      </Collections>
      <Collections>
        <Id>2</Id>
        <ItemName>Item2</ItemName>
        <Image>
          <href>Path 4</href>
        </Image>
        <Image>
          <href>Path 5</href>
        </Image>
      </Collections>
    </Groups>