gpt4 book ai didi

.net - 继承 xdocument/xelement 命名空间问题(谷歌联系人 API)

转载 作者:行者123 更新时间:2023-12-04 16:55:04 25 4
gpt4 key购买 nike

我正在尝试解析 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

问题:
  • 没有更简单的方法将所有匹配的元素转换为 GoogleContacts 吗?然后通过迭代添加每个 1。似乎 GoogleContact 并不是真正的 XElement,因为它在调试器中显示为 {<entry....>}而不是 <entry....>我不确定这些大括号在这里是什么意思,但很奇怪
  • 为什么我需要一次又一次地声明命名空间?有没有办法以某种方式将所有相关的命名空间传递给 GoogleContact?以现在的方式,谷歌拒绝接受数据,因为所有命名空间都变成了“p1”

  • 我很感激关于这个主题的任何建议

    非常感谢你

    编辑

    这是一个更完整的代码示例,根据 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

    最佳答案

    目前还不完全清楚究竟出了什么问题——如果你在任何地方都指定了正确的命名空间,一切都应该没问题。但是,您不需要在所有地方重复这些名称——您可能希望创建类型为 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

    然后你可以在任何地方使用这些“常量”——它们是否有命名空间都没有关系;这最终不会在您的代码中使用,因为您只是适本地引用了“元素名称”或“属性名称”。

    一般来说,改进代码的方法:
  • 如果可以,我仍然建议使用 .NET API;你说你“没有发现它们很有帮助”,但这可能只是意味着你没有足够长的时间调查它们。一旦您掌握了它们的窍门,它们很可能会节省您的时间。
  • 我不会在您提供的代码中使用任何继承 - 无需从 WebClient 派生, XDocumentXElement .如果没有这里的继承,您的代码会更清晰,因为您可以只创建与您尝试建模的对象相关的成员。
  • 您可以使用 LINQ 查询 XDocument并创建联系人集合。例如(再次使用 C#,但 VB 会类似):
    List<GoogleContact> = document.Root
    .Elements(GoogleContact.EntryElementName)
    .Select(element => new GoogleContact(element))
    .ToList();
  • 关于.net - 继承 xdocument/xelement 命名空间问题(谷歌联系人 API),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9856034/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com