Here is a complete dynamic sql approach.  No need to serialize and deserialize the data using XML or JSON.  In this case the list of food items is contained in a temporary table so it reads the column names from tempdb.sys.columns.
The query uses CROSS APPLY to unpivot the columns (of food items) and assigns a ROW_NUMBER() to each non NULL item value.  Something like this
drop table if exists #FoodTable;
go
create table #FoodTable(
  [Name]            varchar(100) not null,
  Cake              varchar(100) null,
  Coca              varchar(100) null,
  [ice-cream]       varchar(100) null);
--select * from dbo.test_actuals
insert #FoodTable values
('Sam', 'one', 'five', 'six'),
('Sara', 'one', 'one', null),
('Jon', 'two', 'two', null);
;with unpvt_cte([Name], item, val, rn) as (
    select f.[Name], v.*, row_number() over (partition by [Name] order by (select null))
    from #FoodTable f
         cross apply (values ('Cake', Cake),
                             ('Coca', Coca),
                             ('IceCream', [ice-cream])) v(item, val)
    where v.val is not null)
select [Name], string_agg(concat(rn, '.', val), ' ') within group (order by rn) answer
from unpvt_cte
group by [Name];
Name        answer
Jon         1.two 2.two
Sam         1.one 2.five 3.six
Sara        1.one 2.one
to make the query dynamic
declare @food_list              nvarchar(max);
select @food_list=string_agg(quotename(concat_ws(',', quotename(sysc.[name], ''''), 
                             quotename(sysc.[name], '[]')), '()'), ',')
from   tempdb.sys.columns sysc
where  object_id = Object_id('tempdb..#FoodTable')
       and [name]<>'Name'; 
declare 
  @sql_prefix             nvarchar(max)=N'
;with unpvt_cte([Name], item, val, rn) as (
    select f.[Name], v.*, row_number() over (partition by [Name] order by (select null))
    from #FoodTable f
         cross apply (values ',
  @sql_suffix             nvarchar(max)=N'
         ) v(item, val)
    where v.val is not null)
select [Name], string_agg(concat(rn, ''.'', val), '' '') within group (order by rn) answer
from unpvt_cte
group by [Name];';
declare
  @sql                    nvarchar(max)=concat(@sql_prefix, @food_list, @sql_suffix);
print(@sql);
exec sp_executesql @sql;
The print statement outputs the following
;with unpvt_cte([Name], item, val, rn) as (
    select f.[Name], v.*, row_number() over (partition by [Name] order by (select null))
    from #FoodTable f
         cross apply (values ('Cake',[Cake]),('Coca',[Coca]),('ice-cream',[ice-cream])
         ) v(item, val)
    where v.val is not null)
select [Name], string_agg(concat(rn, '.', val), ' ') within group (order by rn) answer
from unpvt_cte
group by [Name];