如何在流式传输XML文档时返回强类型对象而不是xelement



我希望能够从流式传输XML文档的代码中返回强类型对象,而不是xelement。假设所讨论的XML文档是:

<?xml version="1.0" encoding="utf-8" ?>
<People>
  <Person>
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
  </Person>
  <Person>
    <FirstName>Adam</FirstName>
    <LastName>Smith</LastName>
  </Person>
  <Person>
    <FirstName>Jane</FirstName>
    <LastName>Smith</LastName>
  </Person>
</People>

目前,我的阅读器代码看起来像这样:

public class PeopleReader
{
    public static IEnumerable<XElement> StreamPerson(string path)
    {
        using (XmlReader rdr = XmlReader.Create(path))
        {
            rdr.MoveToContent();
            while (rdr.Read())
            {
                if (rdr.NodeType == XmlNodeType.Element && rdr.Name == "Person")
                {
                    XElement item = XElement.ReadFrom(rdr) as XElement;
                    if (item != null)
                        yield return item;
                }
            }                  
        }
    }
}

当前主叫码为:

// Current implementation
foreach (var person in PeopleReader.StreamPerson(@"...People.xml"))
{
    MessageBox.Show(person.Element("LastName").Value);
}

我必须调用.Element.Value

我想要的调用代码是:

// Required implementation where person is returned as a strongly typed obj.
foreach (var person in PeopleReader.StreamPerson(@"...People.xml"))
{
    MessageBox.Show(person.LastName);
}

我知道我可以使用xsd.exe生成。xsd文件,然后生成。cs文件,但我不清楚实际步骤。此外,我不确定如何更改阅读器代码以返回生成的类,以便调用代码接收要枚举的强类型对象?也就是说,我如何从xelement转换到强类型类—强制类型转换似乎不是一种选择?

我正在使用VS2015,如果可能的话,我宁愿不使用第三方工具。

提前感谢。

我建议您使用XmlSerializer

var serializer = new XmlSerializer(typeof(Person));
using (var rdr = XmlReader.Create(path))
{
    rdr.MoveToContent();
    while (rdr.Read())
    {
        if (rdr.NodeType == XmlNodeType.Element && rdr.Name == "Person")
        {
            yield return (Person) serializer.Deserialize(rdr);
        }
    }
}

你的类定义如下:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

请看下面的示例。

要为XML生成类,您可以使用xsd.exe(用于XML或XML模式,如果您有的话),或者您可以使用Edit -> Paste Special -> Paste XML as Classes将XML样本复制并粘贴到Visual Studio中。

不返回IEnumerable<XElement>,而是创建Person类型并返回IEnumerable<Person>:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

然后返回它的一个新实例:

public static IEnumerable<XElement> StreamPerson(string path)
{
    using (XmlReader rdr = XmlReader.Create(path))
    {
        rdr.MoveToContent();
        while (rdr.Read())
        {
            XElement item = XElement.ReadFrom(rdr) as XElement;
            if (item != null)
            {
                yield return new Person
                {
                    FirstName = item.Element("FirstName")?.Value,
                    LastName = item.Element("LastName")?.Value
                };
            }
        }
    }
}

更新 -在理解这些xml表示较大类的"轻量级"版本,并且这些类的源代码引用到当前项目之后,我建议:

创建包含轻量级属性的较大类的基类。这样您就不会有代码重复,并且可以从一个转换到另一个。

public class PersonBase
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
public class Person : PersonBase
{
    public string OtherProperty { get; set; }
}

然后使用我上面的方法或者Charles

建议的方法实例化一个对象

最新更新