0

I can't believe how unbelievably complicated this has been...

I have the following XML...

<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://mynamespace.com/books">
  <Rows>
    <Row>
      <Author><Name>Stephen King</Name></Author>
    </Row>  
   </Rows>
</Library>

I would like the Deserialized C# object to read like... Library.Books[0].Author

I have tried a million different combination of XML Attribute Markings to Deserialize, such as...

[XmlRootAttribute("Library", Namespace = "http://mynamespace.com/books", IsNullable = false)]
public class Library
{
    [XmlElement("Rows")]
    public List<Book> Books { get; set; }
}

[XmlRoot("Row")]
public class Book
{
    public Author Author { get; set; }
}

[XmlRoot("Author")]
public class Author
{
    public string Name { get; set; }
}

...and I continually get the "Author" object as null when I try to Deserialze. It almost succeeds...I do get the ArrayList with one Book item in the Books property. But for the life of me I can't get the Author.

Any advice/help would be greatly appreciated!

matt_dev
  • 5,176
  • 5
  • 33
  • 44
  • To be fair, it isn't my object... it's yours. [This](http://msdn.microsoft.com/en-us/library/83y7df3e(v=vs.100).aspx) would probably help you. – M.Babcock Mar 27 '12 at 01:01

2 Answers2

3

Try

public class Library
{
    [XmlArray("Rows")]
    [XmlArrayItem("Row")]
    public List<Book> Books { get; set; }
}
Japple
  • 965
  • 7
  • 14
  • Very nice. Book and Author do not need any extra specifiers at this point. Reserialization of the collection works as well. I'd accept this answer. – Jim H. Mar 27 '12 at 03:18
1

Well if you want to write it by 'hand', you could do with these extension methods: http://searisen.com/xmllib/extensions.wiki

public class Library
{
    XElement self;
    public Library() { self = XElement.Load("libraryFile.xml"); }
    public Book[] Books 
    { 
        get 
        { 
            return _Books ?? 
                (_Books = self.GetEnumerable("Rows/Row", x => new Book(x)).ToArray()); 
        } 
    }
    Book[] _Books ;
}

public class Book
{
    XElement self;
    public Book(XElement xbook) { self = xbook; }
    public Author Author 
    { 
        get { return _Author ??
            (_Author = new Author(self.GetElement("Author")); }
    Author _Author;
}

public class Author
{
    XElement self;
    public Author(XElement xauthor) { self = xauthor; }
    public string Name 
    { 
        get { return self.Get("Name", string.Empty); }
        set { self.Set("Name", value, false); }
    }
}

It requires a bit more boilerplate code to make it so you can add new books, but your post was about reading (deseralizing), so I didn't add it.

Chuck Savage
  • 11,775
  • 6
  • 49
  • 69