简体   繁体   English

解析XML文件并从父节点获取值

[英]Parse XML file and grab value from parent node

XML file looks like this: XML文件如下所示:

<?xml version="1.0"?>
<catalog>
    <book id="bk101">
        <author>Gambardella, Matthew</author>
        <title>XML Developer's Guide</title>
        <genre>Computer</genre>
        <price>44.95</price>
        <publish_date>2000-10-01</publish_date>
        <description>An in-depth look at creating applications with XML.</description>
    </book>
    <book id="bk102">
        <author>Ralls, Kim</author>
        <title>Midnight Rain</title>
        <genre>Fantasy</genre>
        <price>5.95</price>
        <publish_date>2000-12-16</publish_date>
        <description>A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.</description>
    </book>
</catalog>

I need to read all data to my class: 我需要将所有数据读取到我的课程中:

public class Book
{
    public string Id { get; set; }

    public string Author { get; set; }
    public string Title { get; set; }
    public Genre Genre { get; set; }
    public decimal Price { get; set; }
    public DateTime PublishDate { get; set; }
    public string Description { get; set; }

}

Below code doesn't work, I can grab bookId from node, but not Title, Author.. How to achieve that result? 下面的代码不起作用,我可以从节点中获取bookId,但不能从Title,Author中获取。如何实现该结果? This is what I have so far: 这是我到目前为止的内容:

const string filePath = @"C:\Users\Michał\Desktop\books.xml";

XDocument xmlDoc = XDocument.Load(filePath);

var dupa = xmlDoc
    .Descendants("book")
    .Select(x => new Book()
    {
        Id = (string) x.Attribute("bookid"),

        Title = (string) x.Attribute("title") // Title is empty after that code runs

    }).ToList();

id is an attribute of <book> but the other nodes are child XML elements so you need to access them using XContainer.Element(XName name) : id<book>属性 ,但是其他节点是XML子元素,因此您需要使用XContainer.Element(XName name)访问它们:

var dupa = xmlDoc
    .Descendants("book")
    .Select(x => new Book
    {
        Id = (string)x.Attribute("bookid"),
        Author = (string)x.Element("author"),
        Title = (string)x.Element("title"),
        Genre = (Genre)Enum.Parse(typeof(Genre), (string)x.Element("genre")),
        Price = (decimal)x.Element("price"),
        PublishDate = (DateTime)x.Element("publish_date"),
        Description = (string)x.Element("description"),
    }).ToList();

Here I am assuming that Genre is an enum that looks something like: 在这里,我假设Genre是一个看起来像这样的枚举:

public enum Genre
{
    Computer,
    Fantasy,
};

Sample fiddle #1 . 样本小提琴#1

Alternatively, you could create a Catalog type that contains your list of books, annotate it and Book with attributes that control XML serialization , and deserializing everything using XmlSerializer . 或者,您可以创建一个包含您的书籍清单的Catalog类型,使用控制XML序列化的属性对其进行注释,并使用XmlSerializer所有Book进行反序列化

Define your types like so: 像这样定义您的类型:

[XmlRoot(ElementName = "book")]
public class Book
{
    [XmlElement(ElementName = "author")]
    public string Author { get; set; }
    [XmlElement(ElementName = "title")]
    public string Title { get; set; }
    [XmlElement(ElementName = "genre")]
    public Genre Genre { get; set; }
    [XmlElement(ElementName = "price")]
    public decimal Price { get; set; }
    [XmlElement(ElementName = "publish_date")]
    public string PublishDate { get; set; }
    [XmlElement(ElementName = "description")]
    public string Description { get; set; }
    [XmlAttribute(AttributeName = "id")]
    public string Id { get; set; }
}

[XmlRoot(ElementName = "catalog")]
public class Catalog
{
    [XmlElement(ElementName = "book")]
    public List<Book> Books { get; set; }
}

public enum Genre
{
    Computer,
    Fantasy,
};

And then deserialize as follows: 然后反序列化如下:

List<Book> dupa;
using (var reader = XmlReader.Create(filePath))
{
    var serializer = new XmlSerializer(typeof(Catalog));
    dupa = ((Catalog)serializer.Deserialize(reader)).Books;
}

Sample fiddle #2 . 样本小提琴2

Notes: 笔记:

  • Consider changing Genre from an enum to a string . 考虑将Genreenum更改为string With your current model, deserialization will fail if new genres are later added to the XML. 在您当前的模型中,如果以后将新类型添加到XML,反序列化将失败。

  • There are a variety of tools to auto-generate types from XML that are compatible with XmlSerializer . 有多种工具可以从XML自动生成与XmlSerializer兼容的类型。 I used https://xmltocsharp.azurewebsites.net/ and then modified the property names and types as required. 我使用了https://xmltocsharp.azurewebsites.net/ ,然后根据需要修改了属性名称和类型。 Another option is xsd.exe . 另一个选项是xsd.exe For more see Generate C# class from XML . 有关更多信息,请参见从XML生成C#类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM