им пытается разобрать XML, возвращаемого Google Contacts APIнаследуя XDocument/XElement пространства имен (Google Contacts API)
я сделал некоторые вспомогательные классы, чтобы дать мне сильно типизированный доступ к необходимым данным, но не может, кажется, чтобы они работали в тандеме.
я сделал класс, который наследуется GoogleDocument XDocument и GoogleContact, который наследуется XElement
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
вопросы:
- не является более простой способ, чтобы преобразовать все соответствующие элементы GoogleContacts? затем добавив каждый 1 через итерацию. также кажется, что GoogleContact на самом деле не является XElement, как в отладчике, он отображается как
{<entry....>}
вместо<entry....>
им не уверен, что здесь означают эти фигурные скобки, но его нечетные - Почему мне нужно снова и снова объявлять пространства имен? не существует способа каким-то образом перейти на GoogleContact на все соответствующие пространства имен? как его сейчас, Google отказывается принимать данные обратно, как и все пространства имен становятся «p1»
я был бы признателен за любые советы по этому вопросу
спасибо
EDIT
вот более полный пример кода, с изменениями в предложения Джона Скита
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
Почему вы унаследовав от XDocument и XElement? Это звучит как плохая идея для меня - почему бы просто не создать классы, которые * составляют * существующий объект? –
несколько причин: изначально потому, что я сделал это в прошлом для подобных ситуаций, но без пространств имен, а также его естественную подгонку для чего-то, что входит в xml-фрагменты. но более того, потому что в конце мне иногда нужно вызывать 'ToString', чтобы получить точную структуру XML, чтобы отправить обратно в Google для обновлений. –
Ни один из них не звучит как повод для меня. Контакт, естественно, не является элементом XML - это то, как он может быть представлен *. Вы всегда можете переопределить 'ToString()' (или создать отдельный метод), чтобы вернуть XML. –