2017-12-02 127 views
0

XML文件是这样的:解析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> 

我需要的所有数据读取我的课:

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; } 

} 

下面的代码不工作,我可以从节点抓取bookId,但不能标题,作者.. 如何实现该结果?这是我到目前为止有:

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(); 
+1

作者,标题等是Book的后代节点,而不是属性。 – localghost

回答

1

id<book>attribute但其他节点是孩子XML elements所以你需要使用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(); 

在这里,我假设Genre是一个枚举类似于:

public enum Genre 
{ 
    Computer, 
    Fantasy, 
}; 

样例fiddle #1

或者,您可以创建一个包含您的书籍列表中Catalog类型,与attributes that control XML serialization注释,并Book,并使用XmlSerializer反序列化的一切。

定义你的类型,像这样:

[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, 
}; 

然后反序列化如下:

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

样品fiddle #2

注:

  • 考虑从enum改变Genrestring。使用当前的模型,如果新的流派稍后添加到XML中,反序列化将失败。

  • 有多种工具可以自动生成与XmlSerializer兼容的XML类型。我使用http://xmltocsharp.azurewebsites.net/,然后根据需要修改属性名称和类型。另一种选择是xsd.exe。欲了解更多信息,请参阅Generate C# class from XML