【问题标题】:serializing xml tags to c# dictionary将xml标签序列化为c#字典
【发布时间】:2020-04-17 21:18:33
【问题描述】:

我有一个以以下形式返回 xml 的 api

<root>
<sometag>somevalue</sometag>
<sometag>somevalue</sometag>
<Rights>
    <admin>true</admin>
    <admin_employees>true</admin_employees>
    <admin_inventory>true</admin_inventory>
    <admin_purchases>true</admin_purchases>
    <admin_shops>true</admin_shops>
    <admin_void_sale>true</admin_void_sale>
</Rights>
</root>

我正在使用 System.Xml.Serialization,并且在没有强烈键入整个内容的情况下无法让“权利”部分序列化,因为它只使用了一次。

理想情况下,我希望将其序列化为以标签名称为键的字典。我将如何实现这一目标?还是有其他更好的方法?

希望有类似if(Rights["admin"]) ...的用法

【问题讨论】:

  • 您可以使用LinqToXml 来实现。
  • 能否请您也发布您用于反序列化 xml 的代码?

标签: c# xml serialization


【解决方案1】:

因为你提到了使用 XmlSerializer 来反序列化内容,

坚持下去,如果您已经为整个根对象创建了一个类,但又不想为 Rights 集合中的每个标志键入属性,这里还有一个使用 XmlSerializer.Deserialize() 的解决方案来帮助您。

[XmlRoot("root")]
public class RootObject
{
    // . . . other properties
    // . . . if you have them
    // . . . and just don't put here anything
    // . . . if you don't need them
    public XmlElementDictionary<bool> Rights { get; set; }
}

如果您收到的 XML 格式与您在问题中输入的格式完全相同,则以下内容会将 Rights 元素解析为字典。通过实现 IXmlSerializable,我们告诉序列化系统我们想要自己序列化/反序列化这个类型。

请注意,未实现写入和架构支持。

public class XmlElementDictionary<TValue> : Dictionary<string, TValue>, IXmlSerializable
{
    void IXmlSerializable.ReadXml(XmlReader reader)
    {
        string startElementName = reader.Name;
        while (reader.Read())
        {
            string keyName = reader.Name;
            if (keyName == startElementName) break;
            reader.Read(); // Read element value
            base.Add(keyName, (TValue)Convert.ChangeType(reader.Value, typeof(TValue)));
            reader.Read(); // Read end element

        }
    }

    System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() { throw new NotImplementedException(); }
    void IXmlSerializable.WriteXml(XmlWriter writer) { throw new NotImplementedException(); }
}

泛型实现使其可重用于其他类型。可以改进读取逻辑以检查任何属性(如果有属性现在会失败,但应该让您清楚地了解如何仅读取元素及其内部文本)

这里是如何使用它:

static void Main(string[] args)
{
    RootObject rootObject = 
        (RootObject)new XmlSerializer
            (typeof(RootObject)).Deserialize(new StringReader(XML));

    if(rootObject.Rights["admin"])
    {
        . . . .
    }
}

【讨论】:

  • 哦,看起来很完美,一会儿试试看!
【解决方案2】:

见下文:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            Dictionary<string, Boolean> dict = doc.Descendants("Rights").FirstOrDefault().Elements()
                .GroupBy(x => x.Name.LocalName, y => (Boolean)y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-19
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    相关资源
    最近更新 更多