Google Picasa API XML 反序列化

发布于 2024-12-02 09:25:54 字数 5802 浏览 2 评论 0原文

我目前正在使用 Google Picasa API 尝试列出相册。 OAuth 2.0 的代码已编写并可以运行。我可以毫无问题地获取专辑的 XML 列表。过去我很少使用 XML,而且无法将其反序列化。

我尝试使用 XSD.exe 工具生成 .xsd,然后从中生成类,但我立即收到错误:名为“id”的列已属于此数据表。

我不明白为什么,因为第二个 ID 标签嵌套在另一个节点中。谁能引导我走向正确的方向?

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&amp;RGB=0x000000&amp;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&amp;max-results=1000&amp;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&amp;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&amp;v=2' />
    <link rel='edit' type='application/atom+xml'
      href='https://picasaweb.google.com/data/entry/api/user/liz/albumid/albumID/1236820754876000?authkey=authKey&amp;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&amp;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>

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌无敌 2024-12-09 09:25:54

我不知道为什么 xsd.exe 不起作用。根据我的经验,让您抢占先机固然很好,但为要序列化的 XML 文档生成优化的 C# 类并不是万无一失的。还有其他代码生成工具具有类似的功能。 XsdObjectGen 是一个免费的,不确定它是否仍然存在。

在我的评论中,我说另一方面,手动编写类以使用 Xml 序列化程序是非常机械的。

这个部分示例应该可以帮助您入门:

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

此代码仅对这些元素进行反序列化在 FeedList 类中。
如果您需要其他元素,请将它们添加进去。文本元素可以反序列化为简单类型的属性,例如字符串、int 或 DateTime。复杂元素需要是自定义类的属性,并用 XmlType 修饰。

要反序列化多个元素的序列(例如 link 元素或 entry 元素),请定义一个数组,并使用 XmlElement 对其进行修饰,如图所示。双引号内的值是每个所使用的元素名称。 XML 中的属性获取用 C# 代码中的 XmlAttribute 属性修饰的属性,引号中的值为 attr 名称。无值意味着将 xml 中与属性名称同名的属性映射到给定属性。 (用 XmlAttribute 装饰的 C# 代码中名为“rel”的属性将映射到 XML 文档中名为“rel”的 xml 属性值)

如果您关心其他架构中的元素 (像 opensearch 模式等),您需要指定与这些模式中的元素相对应的属性。同样,对 XML 中的复杂类型使用自定义类; XML 中简单(仅限文本)元素的简单 C# 数据类型。对于简单类型,属性上的 XmlElement 属性,或者对于复杂类型,自定义类上的 XmlType 属性,必须指定该元素的 xmlns 命名空间。您不必担心元素前缀 - 命名空间才是重要的。请参阅totalResults 属性作为示例。

XmlElementXmlAttribute 属性缺少未标记的字符串值时,元素名称或属性名称将被假定为属性本身的名称。因此,在上面,属性 totalResults 反序列化 openSearch:totalResults 元素,因为我提供了与 openSearch 对应的 xmlns。

要反序列化 xml 元素的文本节点,请使用 XmlText 属性。

扩展上面的示例,您应该能够反序列化您需要反序列化的所有内容。


编辑
但您可能想使用已经构建的库来执行此操作。
http://code.google.com/p/google-gdata/updates/list

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文