我试图解析Google通讯录API返回的XML
我制作了一些辅助类来给我强大的类型访问必要的数据,但似乎无法使它们协同工作。
我创建了一个继承XDocument的GoogleDocument类和一个继承XElement的GoogleContact
Class GoogleDocument
Inherits XDocument
Dim xnsAtom = XNamespace.Get("http://www.w3.org/2005/Atom")
Sub New()
MyBase.new()
End Sub
Sub New(other As XDocument)
MyBase.New(other)
End Sub
ReadOnly Property Entries As IEnumerable(Of GoogleContact)
Get
Dim feed = Element(xnsAtom + "feed")
Dim ret = New List(Of GoogleContact)
For Each e In feed.Elements(xnsAtom + "entry")
ret.Add(New GoogleContact(e))
Next
Return ret.AsEnumerable
End Get
End Property
End Class
Class GoogleContact
Inherits XElement
Dim xnsGd = XNamespace.Get("http://schemas.google.com/g/2005")
Dim xnsAtom = XNamespace.Get("http://www.w3.org/2005/Atom")
Dim xnsApp = XNamespace.Get("http://www.w3.org/2007/app")
Sub New(other As XElement)
MyBase.new(other)
End Sub
ReadOnly Property ETag As String
Get
Return Attribute(xnsGd + "etag").Value
End Get
End Property
ReadOnly Property ContactID As Integer
Get
Dim uri = Element(xnsAtom + "id").Value
Return uri.Substring(uri.LastIndexOf("/") + 1)
End Get
End Property
ReadOnly Property Edited As DateTime
Get
Return Date.Parse(Element(xnsApp + "edited").Value)
End Get
End Property
End Class
的问题:
{<entry....>}
而不是<entry....>
我不知道这些括号在这里是什么意思,但它的奇怪我很感激有关这个问题的任何建议
非常感谢
修改
这是一个更完整的代码示例,根据Jon Skeet的建议进行更改
Imports System.Net
Imports System.Text
Imports System.IO
Imports System.Collections.Specialized
Imports System.Runtime.CompilerServices
Module Module1
Dim GUserName As String
Dim GPassword As String
Sub Main()
Dim authRequest As HttpWebRequest = HttpWebRequest.Create("https://www.google.com/accounts/ClientLogin")
authRequest.KeepAlive = True
authRequest.ContentType = "application/x-www-form-urlencoded"
authRequest.Method = "POST"
Dim encoder = New ASCIIEncoding
Dim encodedData = encoder.GetBytes("Email=" & GUserName & "&Passwd=" & GPassword & "&source=Consultor&service=cp&accountType=HOSTED_OR_GOOGLE")
authRequest.ContentLength = encodedData.Length
Dim requestStream = authRequest.GetRequestStream
requestStream.Write(encodedData, 0, encodedData.Length)
requestStream.Close()
Dim authResponse = authRequest.GetResponse
Dim readStream = New StreamReader(authResponse.GetResponseStream, encoder)
Dim body = readStream.ReadToEnd
Dim tokens = TextCollection(body, "=", Chr(10))
Dim req2 = New GoogleClient(tokens("auth"))
body = req2.GetString("default/full?max-results=5000")
Dim gDoc = New GoogleDocument(XDocument.Parse(body))
Dim dcx = DBEntities()
Dim pers = dcx.Persons
For Each ge In gDoc.Entries
Dim entry = ge
Dim id As String = entry.ContactID
Dim p As Object '= (From x In pers Where x.GoogleCode = id).FirstOrDefault' cant ompile iin this demo
If p Is Nothing Then Exit For
If entry.Edited > p.LastEdit Then
p.GoogleCode = entry.ContactID
dcx.SaveChanges()
Else
Dim updClient = New GoogleClient(tokens("auth"))
updClient.ETag = entry.ETag
Dim updResp = updClient.PutString("http://www.google.com/m8/feeds/contacts/" & GUserName & "/base/" & entry.ContactID, entry.UpdateXml)
End If
Next
End Sub
Class GoogleClient
Inherits WebClient
Property ETag As String
Const UrlStart = "https://www.google.com/m8/feeds/contacts/"
Sub New(AuthToken As String)
Headers.Add("Content-Type", "application/atom+xml; charset=UTF-8")
Headers.Add("User-Agent", "G-Consultor/GDataGAuthRequestFactory-CS-Version=1.9.0.23118--IEnumerable")
Headers.Add("Authorization", "GoogleLogin auth=" & AuthToken)
Headers.Add("GData-Version", "3.0")
End Sub
Function GetString(Path As String) As String
Return DownloadString(UrlStart & Path)
End Function
Public Function PutString(address As String, data As String) As String
If ETag <> "" Then
Headers.Add("Etag", ETag)
Headers.Add("If-Match", ETag)
End If
Return UploadString(address, "PUT", data)
End Function
End Class
Function TextCollection(Text As String, FieldDelimiter As String, Optional RowDelimiter As String = vbCrLf) As NameValueCollection
Text = Text.RightCut(RowDelimiter)
Dim ret = New NameValueCollection
Dim rows = Text.Split(RowDelimiter)
For Each cl In rows
ret.Add(cl.Substring(0, cl.IndexOf(FieldDelimiter)), cl.Substring(cl.IndexOf(FieldDelimiter) + FieldDelimiter.Length))
Next
Return ret
End Function
Class GoogleDocument
Inherits XDocument
Dim xnsAtom = XNamespace.Get("http://www.w3.org/2005/Atom")
Sub New()
MyBase.new()
End Sub
Sub New(other As XDocument)
MyBase.New(other)
End Sub
ReadOnly Property Entries As IEnumerable(Of GoogleContact)
Get
Dim feed = Element(xnsAtom + "feed")
Dim ret = New List(Of GoogleContact)
For Each e In feed.Elements(xnsAtom + "entry")
ret.Add(New GoogleContact(e))
Next
Return ret.AsEnumerable
End Get
End Property
End Class
Function DBEntities() As Object 'really should return my EF data model
Return Nothing
End Function
<Extension()> Function RightCut(value As String, CutString As String) As String
If Right(value, CutString.Length) = CutString Then value = value.Substring(0, value.Length - CutString.Length)
Return value
End Function
Class GoogleContact
Dim xnsGd = XNamespace.Get("http://schemas.google.com/g/2005")
Dim xnsAtom = XNamespace.Get("http://www.w3.org/2005/Atom")
Dim xnsApp = XNamespace.Get("http://www.w3.org/2007/app")
Dim xContact As XElement
Sub New(entry As XElement)
xContact = entry
End Sub
ReadOnly Property ETag As String
Get
Return xContact.Attribute(xnsGd + "etag").Value
End Get
End Property
ReadOnly Property ContactID As Integer
Get
Dim uri = xContact.Element(xnsAtom + "id").Value
Return uri.Substring(uri.LastIndexOf("/") + 1)
End Get
End Property
ReadOnly Property Edited As DateTime
Get
Return Date.Parse(xContact.Element(xnsApp + "edited").Value)
End Get
End Property
ReadOnly Property UpdateXml
Get
Return "<?xml version=""1.0"" encoding=""utf-8""?>" & xContact.ToString
End Get
End Property
Overrides Function ToString() As String
Return xContact.ToString
End Function
End Class
End Module
答案 0 :(得分:2)
目前还不完全清楚错误的实际情况 - 如果你在任何地方指定正确的命名空间,它应该都没问题。但是,您不需要在整个地方重复这些名称 - 您可能希望创建类型为XName
的共享只读字段以避免拼写错误。为简单起见,我还使用从String
到XName
的隐式转换。在C#中,我将其写为:
private static readonly XNamespace AtomNs = "http://www.w3.org/2005/Atom";
private static readonly XNamespace GoogleDataNs =
"http://schemas.google.com/g/2005";
private static readonly XNamespace AppNs = "http://www.w3.org/2007/app";
// You should work out where to put these, and their visibility
public static readonly XName FeedElementName = AtomNs + "feed";
public static readonly XName EntryElementName = AtomNs + "entry";
public static readonly XName ETagAttributeName = GoogleDataNs + "etag";
// etc
然后你可以在任何地方使用那些“常量” - 它们重要它们有命名空间;这最终不会在您的代码中使用,因为您只是恰当地引用了“元素名称”或“属性名称”。
一般而言,改进代码的方法:
WebClient
,XDocument
或XElement
派生。如果没有继承,您的代码将更加清晰,因为您可以只创建与您尝试建模的对象相关的成员。您可以使用LINQ查询XDocument
并创建联系人集合。例如(再次使用C#,但VB类似):
List<GoogleContact> = document.Root
.Elements(GoogleContact.EntryElementName)
.Select(element => new GoogleContact(element))
.ToList();