问题
I'm currently working with the Google Picasa API trying to list albums. The code to for OAuth 2.0 is written and working. I can get the XML list of albums without any issue. I have worked very little with XML in the past and I can't get it to deserialize.
I tried to use the XSD.exe tool to generate a .xsd and then classes from that but I get an error right away: A column named 'id' already belongs to this DataTable.
I can't figure out why because the second ID tag is nested in an other node. Can anyone put me in the right direction?
XML:
<?xml version='1.0' encoding='utf-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/'
xmlns:exif='http://schemas.google.com/photos/exif/2007'
xmlns:geo='http://www.w3.org/2003/01/geo/wgs84_pos#'
xmlns:gml='http://www.opengis.net/gml'
xmlns:georss='http://www.georss.org/georss'
xmlns:batch='http://schemas.google.com/gdata/batch'
xmlns:media='http://search.yahoo.com/mrss/'
xmlns:gphoto='http://schemas.google.com/photos/2007'
xmlns:gd='http://schemas.google.com/g/2005'
gd:etag='W/"CkABRXY8fip7ImA9WxVVGE8."'>
<id>https://picasaweb.google.com/data/feed/api/user/liz</id>
<updated>2009-03-12T01:19:14.876Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/photos/2007#user' />
<title>liz</title>
<subtitle></subtitle>
<icon>https://iconPath/liz.jpg</icon>
<link rel='http://schemas.google.com/g/2005#feed'
type='application/atom+xml'
href='https://picasaweb.google.com/data/feed/api/user/liz' />
<link rel='http://schemas.google.com/g/2005#post'
type='application/atom+xml'
href='https://picasaweb.google.com/data/feed/api/user/liz' />
<link rel='alternate' type='text/html'
href='http://picasaweb.google.com/liz' />
<link rel='http://schemas.google.com/photos/2007#slideshow'
type='application/x-shockwave-flash'
href='http://picasaweb.google.com/s/c/bin/slideshow.swf?host=picasaweb.google.com&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2Fliz%3Falt%3Drss' />
<link rel='self' type='application/atom+xml'
href='https://picasaweb.google.com/data/feed/api/user/liz?start-index=1&max-results=1000&v=2' />
<author>
<name>Liz</name>
<uri>http://picasaweb.google.com/liz</uri>
</author>
<generator version='1.00' uri='http://picasaweb.google.com/'>
Picasaweb</generator>
<openSearch:totalResults>1</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>1000</openSearch:itemsPerPage>
<gphoto:user>liz</gphoto:user>
<gphoto:nickname>Liz</gphoto:nickname>
<gphoto:thumbnail>
https://thumbnailPath/liz.jpg</gphoto:thumbnail>
<gphoto:quotalimit>1073741824</gphoto:quotalimit>
<gphoto:quotacurrent>32716</gphoto:quotacurrent>
<gphoto:maxPhotosPerAlbum>500</gphoto:maxPhotosPerAlbum>
<entry gd:etag='"RXY8fjVSLyp7ImA9WxVVGE8KQAE."'>
<id>https://picasaweb.google.com/data/entry/api/user/liz/albumid/albumID</id>
<published>2005-06-17T07:09:42.000Z</published>
<updated>2009-03-12T01:19:14.000Z</updated>
<app:edited xmlns:app='http://www.w3.org/2007/app'>
2009-03-12T01:19:14.000Z</app:edited>
<category scheme='http://schemas.google.com/g/2005#kind'
term='http://schemas.google.com/photos/2007#album' />
<title>lolcats</title>
<summary>Hilarious Felines</summary>
<rights>public</rights>
<link rel='http://schemas.google.com/g/2005#feed'
type='application/atom+xml'
href='https://picasaweb.google.com/data/feed/api/user/liz/albumid/albumID?authkey=authKey&v=2' />
<link rel='alternate' type='text/html'
href='http://picasaweb.google.com/lh/album/aFDUU2eJpMHZ1dP5TGaYHxtMTjNZETYmyPJy0liipFm0?authkey=authKey' />
<link rel='self' type='application/atom+xml'
href='https://picasaweb.google.com/data/entry/api/user/liz/albumid/albumID?authkey=authKey&v=2' />
<link rel='edit' type='application/atom+xml'
href='https://picasaweb.google.com/data/entry/api/user/liz/albumid/albumID/1236820754876000?authkey=authKey&v=2' />
<link rel='http://schemas.google.com/acl/2007#accessControlList'
type='application/atom+xml'
href='https://picasaweb.google.com/data/entry/api/user/liz/albumid/albumID/acl?authkey=authKey&v=2' />
<author>
<name>Liz</name>
<uri>http://picasaweb.google.com/liz</uri>
</author>
<gphoto:id>albumID</gphoto:id>
<gphoto:location>Mountain View, CA</gphoto:location>
<gphoto:access>public</gphoto:access>
<gphoto:timestamp>1118992182000</gphoto:timestamp>
<gphoto:numphotos>1</gphoto:numphotos>
<gphoto:numphotosremaining>499</gphoto:numphotosremaining>
<gphoto:bytesUsed>23044</gphoto:bytesUsed>
<gphoto:user>liz</gphoto:user>
<gphoto:nickname>Liz</gphoto:nickname>
<media:group>
<media:title type='plain'>lolcats</media:title>
<media:description type='plain'>Hilarious
Felines</media:description>
<media:keywords></media:keywords>
<media:content url='https://imagePath/Lolcats.jpg' type='image/jpeg' medium='image' />
<media:thumbnail url='https://thumbnailPath/Lolcats.jpg' height='160' width='160' />
<media:credit>Liz</media:credit>
</media:group>
</entry>
...more entries similar to the one above here...
</feed>
回答1:
I don't know why xsd.exe is not working. In my experience it's good to give you a head start but it not foolproof in generating optimized C# classes for the XML document you want to serialize. There are other code-gen tools that do similar. XsdObjectGen is a free one, not sure if it is still around.
In my comment, I said On the other hand it's pretty mechanical to hand-code your class to work with the Xml Serializer.
This partial example ought to get you started:
[XmlType("generator", Namespace="http://www.w3.org/2005/Atom")]
public partial class FeedGenerator
{
[XmlAttribute]
public string version { get; set; }
[XmlAttribute]
public string uri { get; set; }
[XmlText]
public string text { get; set; }
}
[XmlType("category", Namespace="http://www.w3.org/2005/Atom")]
public partial class FeedCategory
{
[XmlAttribute]
public string scheme { get; set; }
[XmlAttribute]
public string term { get; set; }
}
[XmlType("entry", Namespace="http://www.w3.org/2005/Atom")]
public partial class FeedEntry
{
public FeedCategory category { get; set; }
public string title { get; set; }
public string summary { get; set; }
}
[XmlType("author", Namespace="http://www.w3.org/2005/Atom")]
public partial class FeedAuthor
{
public string name { get; set; }
public string uri { get; set; }
}
[XmlType("link", Namespace="http://www.w3.org/2005/Atom")]
public partial class FeedLink
{
[XmlAttribute]
public string rel { get; set; }
[XmlAttribute]
public string @type { get; set; }
[XmlAttribute]
public string href { get; set; }
}
[XmlType("feed", Namespace="http://www.w3.org/2005/Atom")]
[XmlRoot("feed", Namespace="http://www.w3.org/2005/Atom")]
public partial class FeedList
{
public string id { get;set; }
public string title { get;set; }
public string icon { get;set; }
[XmlElement("link")]
public FeedLink[] links { get;set; }
public FeedGenerator generator { get;set; }
[XmlElement(Namespace="http://a9.com/-/spec/opensearch/1.1/")]
public int totalResults { get;set; }
[XmlElement("entry")]
public FeedEntry[] entries { get; set; }
}
This code de-serializes just those elements in the FeedList class.
If you want additional elements, add them in. A text element can be deserialized as a property of a simple type, like a string, int, or DateTime. A complex element needs to be a property of a custom class, decorated with XmlType
.
To deserialize a sequence of multiple elements, like the link
elements or the entry
elements, define an array, and decorate it with XmlElement
as shown. The values inside the double-quotes are the element names used for each. Attributes in the XML get properties decorated with the XmlAttribute
attribute in the C# code, and the value in the quotes is the attr name. No value means to map the attribute in the xml that has the same name as the property name, into the given property. (A property named "rel" in the C# code decorated with XmlAttribute
gets mapped to the xml attribute value with the name "rel" in the XML document)
If you care about the elements from the other schema (like the opensearch schema, etc), you need to specify properties corresponding to the elements from those schema. Again, use custom classes for complex types in the XML; simple C# datatypes for simple (text only) elements in the XML. For a simple type, the XmlElement
attribute on the property, or, for a complex type, the XmlType
attribute on the custom class, must specify the xmlns namespace for that element. You need not worry about the element prefix - the namespace is what is important. See the totalResults property as an example.
When an XmlElement
or XmlAttribute
attribute lacks an unlabeled string value, the element name or attribute name is assumed to be the name of the property itself. So in the above, the property totalResults
deserializes the openSearch:totalResults
element, because I've provided the xmlns corresponding to openSearch.
To deserialize the text node of an xml element, use an XmlText
attribute.
Extend the example above and you should be able to deserialize everything you need to deserialize.
EDIT
But you may wanna use a library that is already built to do this.
http://code.google.com/p/google-gdata/updates/list
来源:https://stackoverflow.com/questions/7263822/google-picasa-api-xml-deserialization