在父元素内将对象序列化为 XML

2023-12-07

我有一个 WPF C# 程序,有时我需要将对象序列化为 XML。在其他地方,我一直在使用这个:

TextWriter writer = new StreamWriter(xmlFilePath);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MYOBJECT_TYPE));

try
{
    xmlSerializer.Serialize(writer, MYOBJECT);

}
catch (Exception ex)
{
    MessageBox.Show("Exception occured while writing to Xml" + ex.Message);
}
finally
{
    writer.Close();
}

这太棒了,但这意味着我必须为每个要序列化的对象提供不同的 XML 文件。如何使用此方法(只需最少的修改)将对象序列化为 XML在父元素内?这样,当我稍后想要反序列化该对象时,我可以找到我想要的元素,并反序列化该元素内的所有内容。

根据要求,这里是CreateDefaultXml();:

static void CreateDefaultXml()
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml("<StoredObjects></StoredObjects>");
    XmlNode root = doc.DocumentElement;
    try
    {
        doc.Save(xmlFilePath);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception occured while creating Xml" + ex.InnerException);
    }
}

EDIT:

目前,这就是我所拥有的(但它引发了异常There was an error generating the XML document.)

if (!File.Exists(xmlFilePath))
    CreateDefaultXml();

XDocument doc = XDocument.Load(xmlFilePath);
var element = doc.Descendants("Object").Where(x => x.Attribute("Name").Value.Equals("objectName")).SingleOrDefault();

if (element == null)
{
    element = new XElement("Object", new XAttribute("Name", objectName));
    doc.Element("StoredObjects").Add(element);
}

XmlWriter writer = element.CreateWriter();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MYOBJECT_TYPE));

try
{
    xmlSerializer.Serialize(writer, MYOBJECT);

}
catch (Exception ex)
{
    MessageBox.Show("Exception occured while writing to Xml: " + ex.Message);
}
finally
{
    writer.Close();
    doc.Save(xmlFilePath);
}

您正在尝试直接序列化到某些嵌套的XElement里面一个XDocument using XmlSerializer。不幸的是,当直接序列化到 LINQ-to-XML 时XElement using XmlSerializer和...一起XContainer.CreateWriter(),实际上需要序列化为空XDocument从而创建其根元素。 (我不确定为什么存在这个限制,但确实存在。)由于这不能满足您的需求,因此很容易序列化为暂时的 XDocument,删除其根节点,然后将该节点添加到整个元素层次结构中。

此外,当使用objectName如果已经存储了 XML 数据,则需要删除旧数据。

我将您的代码重构为扩展方法来实现此目的:

public static class XmlExtensions
{
    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
    {
        using (var reader = element.CreateReader())
        {
            object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
            if (result is T)
                return (T)result;
        }
        return default(T);
    }

    public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer = null)
    {
        var doc = new XDocument();
        using (var writer = doc.CreateWriter())
            (serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj);
        var element = doc.Root;
        if (element != null)
            element.Remove();
        return element;
    }

    public static XName ContainerElementName { get { return (XName)"Object"; } }

    public static XName ContainerAttributeName { get { return (XName)"Name"; } }

    public static XElement SetItem<T>(this XDocument doc, string attributeValue, T obj)
    {
        return doc.SetItem(ContainerElementName, ContainerAttributeName, attributeValue, obj);
    }

    static XElement SetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue, T obj)
    {
        if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null)
            throw new ArgumentNullException();
        if (doc.Root == null)
            throw new ArgumentException("doc.Root == null");
        var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault();
        if (container == null)
        {
            container = new XElement(containerElementName, new XAttribute(containerAttributeName, attributeValue));
            doc.Root.Add(container);
        }
        else
        {
            // Remove old content.
            container.RemoveNodes();
        }

        var element = obj.SerializeToXElement();
        container.Add(element);
        return element;
    }

    public static T GetItem<T>(this XDocument doc, string attributeValue)
    {
        return doc.GetItem<T>(ContainerElementName, ContainerAttributeName, attributeValue);
    }

    static T GetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue)
    {
        if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null)
            throw new ArgumentNullException();
        if (doc.Root == null)
            throw new ArgumentException("doc.Root == null");
        var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault();
        if (container == null)
            return default(T);
        var element = container.Elements().SingleOrDefault();
        if (element == null)
            return default(T);
        return element.Deserialize<T>();
    }

    public static XDocument CreateDefaultXDocument()
    {
        var xml = @"<StoredObjects></StoredObjects>";
        return XDocument.Parse(xml);
    }
}

现在你可以做

doc.AddItem(MYOBJECT, objectName);

然后

var MYOBJECT2 = doc.GetItem<MYOBJECT_TYPE>(objectName);

Example fiddle.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在父元素内将对象序列化为 XML 的相关文章

随机推荐

  • Xcode Swift am/pm 时间转为 24 小时格式

    我正在尝试将 am pm 格式时间转换为 24 小时格式时间 6 35 PM to 18 35 我在操场上尝试了这段代码 但似乎没有 如果我有时间独自工作 let dateAsString 02 12 15 6 35 PM let date
  • 为什么循环顺序会影响二维数组迭代时的性能?

    下面是两个几乎相同的程序 除了我切换了i and j周围的变数 它们运行的 时间不同 有人可以解释为什么会发生这种情况吗 版本1 include
  • python/tkinter 绘图程序撤消函数

    我尝试在我的绘画程序中添加一个撤消功能 该功能从画布中删除对象 创建的每个对象都附加到堆栈中 我尝试了它 它可以工作 但屏幕不会仅在第一个撤消时更新 因此如果我绘制 3 条线然后我撤消什么也不会发生 当我一次又一次撤消时 第二行和第三行将被
  • 在 ImageView 上的 OnTouch 中返回 false,但事件仍然被消耗

    我在用ImageView onTouch 我返回 falseACTION MOVE但仍然是onTouch 事件被消耗 imageView setOnTouchListener new View OnTouchListener Overrid
  • 交换字符串中的大小写[重复]

    这个问题在这里已经有答案了 我正在尝试解决Hackerrank 中的这项挑战 它要求将所有小写字母转换为大写字母 反之亦然 我尝试使用以下代码 def swap case s length len s i 0 while length if
  • 从 R 闪亮的 selectInput 中过滤

    我试图让用户上传 csv 文件 然后获取该 csv 文件的一列 因子 并创建用户输入 以确定将为数据框选择该字段中的哪个唯一名称 因此 如果我有以下示例 data frame COURSE VALUE 1 A 7 2 C 2 3 C 2 4
  • 在 SSIS 中动态更改服务器名称

    我的 SSIS 包在开发周期 开发 QA 暂存和生产 期间会经历多个环境 因此我想使用 SSIS 中的配置来设置连接管理器中的服务器名称 这样我就不会不需要手动完成此操作 我读过有关使用 xml 配置文件 SQL 配置表和环境变量的内容 然
  • 谷歌地图:未捕获的类型错误:类型错误

    在几个页面上 我开始收到上述错误 但仅在 Chrome 中 这是一些简单的代码来演示该错误
  • 使用 boost::dynamic_bitset 作为键值对序列化 boost::bimap

    我有兴趣序列化boost bimap含有boost dynamic bitset这样我就可以保存它并在需要时加载回来 我已经尝试这样做 但遇到了很多错误 我随身携带的代码如下 Example program include
  • python 中的布尔值是可变的吗?

    我在 python 中有以下代码 def update request id success 0 try product Mattress objects get id id success 1 except Mattress DoesNo
  • C# 内存地址和变量

    在C 中 有没有办法 获取存储在a中的内存地址 引用类型变量 获取a的内存地址 多变的 EDIT int i int pi i 如何打印 pi 的十六进制值 对于 2 运算符的工作方式与 C 中相同 如果变量不在堆栈上 您可能需要使用fix
  • 从“SecKeychainFindGenericPassword”给出的“SecKeychainItemRef”中提取“用户名”?

    从这个问题 我知道你可以使用SecKeychainFindGenericPassword without用户名值 它仍然会返回给定服务的钥匙串项 但是我如何获取用户名呢 仅使用服务名称获取存储在钥匙串中的用户名 或者 您应该在哪里存储用户名
  • 是否可以将网页内容读入字符串中,以便我可以解析数据?

    我希望能够让我的 iPhone 将 URL 或者实际上是 url 指向的文件 加载到字符串中 我希望能够执行此操作的原因是这样我就可以解析字符串以查找标签并从中提取一些值 这些文件主要是网页 例如 html 或 asp 等 有人能给我一些提
  • 导出并发布 Typescript 中的所有类型和接口

    我正在尝试发布一个打字稿库 我不清楚如何公开所有类型和接口 这是我的设置 mylib src types mytypes ts index ts package json tsconfig json index ts import MyIn
  • Firefox - 删除未修饰复选框的边框

    我有一个复选框appearance none 这在 Chrome 中有效 但在 Firefox 中它留下了一个我无法删除的插入边框 我努力了border none已经 我这里有一个小提琴 http jsfiddle net jcJJ5 不幸
  • 根据 HTML 文本匹配产品价格

    我正在尝试在字符串上使用简单的正则表达式来获取定价信息 但是我的preg match all根本就是没有找到它应该找到的东西 我正在寻找例如 or 或者有时货币符号可能被编码为 HTML 实体 例如对于英镑 pound or 163 使用有
  • Django:在模型 save() 方法中返回序列化器 ValidationError

    我使用 django rest framework 在 Django 框架内创建 Rest API 并且可以返回任何validationError除了序列化器方法之外 但是 我想知道是否有可能返回错误save Django的方法model被
  • 将函数更改为 PDO

    这是我的api中使用的语句 这是第二个 result下面整个函数中的变量 如何将其更改为使用 PDO result query SELECT p IdPhoto p device token title p IdUser FROM phot
  • 如何在nodejs中向mysql查询回调传递参数

    我试图找出将自定义数据传递到查询调用以在回调中可用的正确方法 我在nodejs 中使用MySQL 库 所有最新版本 我调用了 connection query sql function err result 我找不到一种方法来 1 将自定义
  • 在父元素内将对象序列化为 XML

    我有一个 WPF C 程序 有时我需要将对象序列化为 XML 在其他地方 我一直在使用这个 TextWriter writer new StreamWriter xmlFilePath XmlSerializer xmlSerializer