Как XML десериализовать словарь, который скрыт в другом элементе?

Я пишу sp, который может быть полезен для этой цели, в основном это sp pivot любая таблица и возвращает новую таблицу, поворачиваемую или возвращающую только набор данных, это способ ее выполнения:

Exec dbo.rs_pivot_table @schema=dbo,@table=table_name,@column=column_to_pivot,@agg='sum([column_to_agg]),avg([another_column_to_agg]),',
        @sel_cols='column_to_select1,column_to_select2,column_to_select1',@new_table=returned_table_pivoted;

обратите внимание, что в параметре @agg имена столбцов должны быть с '[', а параметр должен заканчиваться запятой ','

SP

Create Procedure [dbo].[rs_pivot_table]
    @schema sysname=dbo,
    @table sysname,
    @column sysname,
    @agg nvarchar(max),
    @sel_cols varchar(max),
    @new_table sysname,
    @add_to_col_name sysname=null
As
--Exec dbo.rs_pivot_table dbo,##TEMPORAL1,tip_liq,'sum([val_liq]),sum([can_liq]),','cod_emp,cod_con,tip_liq',##TEMPORAL1PVT,'hola';
Begin

    Declare @query varchar(max)='';
    Declare @aggDet varchar(100);
    Declare @opp_agg varchar(5);
    Declare @col_agg varchar(100);
    Declare @pivot_col sysname;
    Declare @query_col_pvt varchar(max)='';
    Declare @full_query_pivot varchar(max)='';
    Declare @ind_tmpTbl int; --Indicador de tabla temporal 1=tabla temporal global 0=Tabla fisica

    Create Table #pvt_column(
        pivot_col varchar(100)
    );

    Declare @column_agg table(
        opp_agg varchar(5),
        col_agg varchar(100)
    );

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(@table) AND type in (N'U'))
        Set @ind_tmpTbl=0;
    ELSE IF OBJECT_ID('tempdb..'+ltrim(rtrim(@table))) IS NOT NULL
        Set @ind_tmpTbl=1;

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(@new_table) AND type in (N'U')) OR 
        OBJECT_ID('tempdb..'+ltrim(rtrim(@new_table))) IS NOT NULL
    Begin
        Set @query='DROP TABLE '+@new_table+'';
        Exec (@query);
    End;

    Select @query='Select distinct '+@column+' From '+(case when @ind_tmpTbl=1 then 'tempdb.' else '' end)+@schema+'.'+@table+' where '+@column+' is not null;';
    Print @query;

    Insert into #pvt_column(pivot_col)
    Exec (@query)

    While charindex(',',@agg,1)>0
    Begin
        Select @aggDet=Substring(@agg,1,charindex(',',@agg,1)-1);

        Insert Into @column_agg(opp_agg,col_agg)
        Values(substring(@aggDet,1,charindex('(',@aggDet,1)-1),ltrim(rtrim(replace(substring(@aggDet,charindex('[',@aggDet,1),charindex(']',@aggDet,1)-4),')',''))));

        Set @agg=Substring(@agg,charindex(',',@agg,1)+1,len(@agg))

    End

    Declare cur_agg cursor read_only forward_only local static for
    Select 
        opp_agg,col_agg
    from @column_agg;

    Open cur_agg;

    Fetch Next From cur_agg
    Into @opp_agg,@col_agg;

    While @@fetch_status=0
    Begin

        Declare cur_col cursor read_only forward_only local static for
        Select 
            pivot_col 
        From #pvt_column;

        Open cur_col;

        Fetch Next From cur_col
        Into @pivot_col;

        While @@fetch_status=0
        Begin

            Select @query_col_pvt='isnull('+@opp_agg+'(case when '+@column+'='+quotename(@pivot_col,char(39))+' then '+@col_agg+
            ' else null end),0) as ['+lower(Replace(Replace(@opp_agg+'_'+convert(varchar(100),@pivot_col)+'_'+replace(replace(@col_agg,'[',''),']',''),' ',''),'&',''))+
                (case when @add_to_col_name is null then space(0) else '_'+isnull(ltrim(rtrim(@add_to_col_name)),'') end)+']'
            print @query_col_pvt
            Select @full_query_pivot=@full_query_pivot+@query_col_pvt+', '

            --print @full_query_pivot

            Fetch Next From cur_col
            Into @pivot_col;        

        End     

        Close cur_col;
        Deallocate cur_col;

        Fetch Next From cur_agg
        Into @opp_agg,@col_agg; 
    End

    Close cur_agg;
    Deallocate cur_agg;

    Select @full_query_pivot=substring(@full_query_pivot,1,len(@full_query_pivot)-1);

    Select @query='Select '+@sel_cols+','+@full_query_pivot+' into '+@new_table+' From '+(case when @ind_tmpTbl=1 then 'tempdb.' else '' end)+
    @schema+'.'+@table+' Group by '+@sel_cols+';';

    print @query;
    Exec (@query);

End;
GO

Это пример выполнения:

Exec dbo.rs_pivot_table @schema=dbo,@table=##TEMPORAL1,@column=tip_liq,@agg='sum([val_liq]),avg([can_liq]),',@sel_cols='cod_emp,cod_con,tip_liq',@new_table=##TEMPORAL1PVT;

, тогда Select * From ##TEMPORAL1PVT вернется:

0
задан user9346149 13 July 2018 в 08:15
поделиться

2 ответа

Ваша структура данных не очень подходит для вашего xml. Если у вас простой тип данных, например int или string, вы можете сериализовать и дезацинировать непосредственно в xml-узел. Если у вас есть более сложная структура данных, такая как ваш Firnedship -node, вам нужен вложенный узел.

Сказав это, ваша структура данных должна быть похожа на следующую:

public class SaveGame
{
    public Player player { get; set; }
}

public class Player
{
    public item[] friendshipData { get; set; }
}

public class item
{
    public Key key { get; set; }
    public Friendship value { get; set; }
}

// add this class with a single string-field
public class Key
{
    public string @string { get; set;  }
}

public class Friendship
{
    public int Points { get; set; }
}

В качестве альтернативы рассмотрим следующие соглашения об именах, которые предоставляют классы и члены этих классов имен PascaleCase, например FriendshipData, Item и Key. Это, однако, предполагает, что у вас есть сопоставление этих имен с вашими именами в xml. Это можно сделать, используя XmlElementAttribute:

public class Player
{
    [XmlElement("friendshipData ")] // see here how to change the name within the xml
    public item[] FriendshipData { get; set; }
}
0
ответ дан HimBromBeere 17 August 2018 в 13:30
поделиться

Поскольку вам нужны только два значения из Xml, я бы не использовал сериализацию. Вы можете получить словарь с одной командой linq.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication51
{

    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";

        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            Dictionary<string, int> players = doc.Descendants("item")
                .GroupBy(x => (string)x.Descendants("string").FirstOrDefault(), y => (int)y.Descendants("Points").FirstOrDefault())
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

        }
    }


}
0
ответ дан jdweng 17 August 2018 в 13:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: