【问题标题】:How could I efficiently convert an old XML object to a newly updated XML object?如何有效地将旧的 XML 对象转换为新更新的 XML 对象?
【发布时间】:2016-04-26 05:28:38
【问题描述】:

我正在尝试建立一种可靠的方法来更新我的软件,以确保我可以在发布程序更新时顺利更新用户的文件。该软件是用 C# 编写的。

假设我有一个人对象:

 - Name
 - DoB
 - Nationality

这就是我的 person 类的 0.1 版。将来,为了举例,我会在 person 对象(v0.2)中引入一些新的字段。

 - Name
 - DoB
 - Nationality
 - Temperament <- NEW
 - Job <- NEW

显然我需要将旧对象更新为新对象。我目前正在做的事情如下:

  1. 将 0.1 对象读入版本化类(如 Person01.cs)。
  2. 用旧对象的字段填充新对象。
  3. 使用默认值填充新对象的新字段。
  4. 写出文件。

这似乎非常低效。每次我进行任何更改时,它都需要大量的自定义编码。必须有更好的方法来做到这一点,但由于这是我第一次真正使用 XML,我不知道该怎么做。您能提供的任何帮助将不胜感激。我已经寻找了解决这个问题的方法,但我只找到了不相关的结果。

【问题讨论】:

  • 谢谢,好电话。这有助于提高可读性。好久没发帖了。
  • 如果您手动创建 xml,那会很麻烦。您使用的是 XmlSerializer:msdn.microsoft.com/en-us/library/bb675182.aspx 吗?
  • 是的 System.Xml.Serialization
  • 您是否尝试将旧 xml 反序列化为新对象 (v2),这应该允许您跳过步骤 1 和 2?
  • 我最初尝试过,但没有成功。也许我只是做错了什么……那是你可以直接做的事情吗?

标签: c# xml io


【解决方案1】:

我们有一个 Person 对象:

public class Person
{
    public string Name { get; set; }
    public DateTime DoB { get; set; }
    public string Nationality { get; set; }
}

然后我们添加新属性。不需要有不同版本的类!只需添加属性和默认构造函数,在其中设置新的属性值。反序列化会设置这些值,而不是丢失。

public class Person
{
    public Person()
    {
        // set default value
        Temperament = "hot";
        Job = "office slave";
    }

    public string Name { get; set; }
    public DateTime DoB { get; set; }
    public string Nationality { get; set; }

    public string Temperament { get; set; }
    public string Job { get; set; }
}

【讨论】:

  • 非常感谢!就是这么简单。正是我希望找到的。现在,当我更新时,我需要做的就是为每个新变量添加默认值。
【解决方案2】:

您可以通过将旧 xml 反序列化为新对象来缩短步骤 1 和 2,例如假设你有一个人 v1:

[XmlRoot("Person")]
public class PersonV1
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

然后您将其升级为 person v2,例如:

[XmlRoot("Person")]
public class PersonV2
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string MiddleName { get; set; }
    public DateTime BirthDate { get; set; }
}

现在您可以使用您为人员 v1 读取的数据填充人员 v2,例如:

// read from person v1
var p1 = new PersonV1();
p1.FirstName = "Jeff";
p1.LastName = "Price";
var xmlSerializer = new XmlSerializer(typeof(PersonV1));
var stream = new MemoryStream();
xmlSerializer.Serialize(stream, p1);
var xmlStringP1 = Encoding.ASCII.GetString(stream.ToArray());

// populate to person v2
var deserializer = new XmlSerializer(typeof(PersonV2));
TextReader reader = new StringReader(xmlStringP1);
var p2 = (PersonV2)deserializer.Deserialize(reader);

// further, set defaults for person v2

您可以在此处探索 xml 序列化的更多自定义:http://www.codeproject.com/Articles/483055/XML-Serialization-and-Deserialization-Part-1

【讨论】:

  • 我正在尝试这个想法,但它似乎并不适合我。我收到一个错误,反序列化程序似乎不喜欢类具有不同名称的事实“InvalidOperationException: 不是预期的”
  • 是的,这就是为什么这个地方有一个 XmlRoot 属性。您是否使用它来消除不同类名的影响?另请查看底部链接中的其他选项
  • 你是对的,那是我的错误。我同意亚历克斯所说的,但你的回答是很好的信息谢谢。
【解决方案3】:

一个很好的简单解决方案是使用 XSL 转换。您可以简单地将转换应用于 XML 文件或带有 XML 数据的字符串,然后添加新属性。可以在 here 找到如何在 C# 中执行此操作的示例。

一个示例 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<person>
    <name>John</name>
    <DoB>2016-01-01</DoB>
</person>

一个示例 XSL 文件:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" encoding="UTF-8" indent="no"/>
    <xsl:template match="/">
        <person>
            <xsl:element name="name">
                <xsl:value-of select="/person/name"/>
            </xsl:element>
            <xsl:element name="DoB">
                <xsl:value-of select="/person/DoB"/>
            </xsl:element>
            <Temperament>Quick to anger</Temperament>
            <Job>Unemployed</Job>
        </person>
    </xsl:template>
</xsl:stylesheet>

结果是:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <name>John</name>
    <DoB>2016-01-01</DoB>
    <Temperament>Quick to anger</Temperament>
    <Job>Unemployed</Job>
</person>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2011-12-10
    • 2014-07-07
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    相关资源
    最近更新 更多