【问题标题】:Collect value from single xml attribute within element vb.net从元素 vb.net 中的单个 xml 属性中收集值
【发布时间】:2017-09-28 20:54:53
【问题描述】:

几天来,我一直在尝试弄清楚如何使它工作(我最终陷入了再次查看相同文章的循环,因为您已经在谷歌上搜索了很多问题的组合)

我看过Read XML in VB.netHow to read an XML FileHow to read XML elements in VB.NETRetrieve single attribute value from an xml doc element 其中最后一个似乎指向我正确的方向,但是在运行DWRoelands 指定的代码时,我收到“System.Collections.Generic.List`1[ System.String]" 到控制台输出。

请参阅下面的 XML,我需要从 /Files/File/Link 元素中的 HREF 属性中提取 https://server/transfer/descriptor.ovf,并且仅适用于列为 descriptor.ovf 的文件(我运行的第二个 XML 文件有另一个文件为 VMDK 列出)

谢谢

XML 片段:

<?xml version="1.0" encoding="UTF-8"?>
<VApp href="https://#####/api/vApp/vapp-##">
    <Link rel="down"/>
    <Description>Test vAPP</Description>
    <Tasks>
        <Task cancelRequested="false" >
            <Link rel="task:cancel" />
            <Progress>1</Progress>
            <Details/>
        </Task>
    </Tasks>
    <Files>
        <File bytesTransferred="0" size="-1" name="descriptor.ovf">
            <Link rel="upload:default" href="https://server/transfer/descriptor.ovf"/>
        </File>
    </Files>
    <InMaintenanceMode>false</InMaintenanceMode>
</VApp>

整个 XML:

<?xml version="1.0" encoding="UTF-8"?>
<VApp xmlns="http://www.vmware.com/vcloud/v1.5" ovfDescriptorUploaded="false" deployed="false" status="0" name="Test vAPP" id="urn:vcloud:vapp:#####" href="https://server/api/vApp/vapp-#####" type="application/vnd.vmware.vcloud.vApp+xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 https://server/api/v1.5/schema/master.xsd">
    <Link rel="down" href="https://server/api/vApp/vapp-#####/controlAccess/" type="application/vnd.vmware.vcloud.controlAccess+xml"/>
    <Link rel="up" href="https://server/api/vdc/#####" type="application/vnd.vmware.vcloud.vdc+xml"/>
    <Link rel="down" href="https://server/api/vApp/vapp-#####/owner" type="application/vnd.vmware.vcloud.owner+xml"/>
    <Link rel="down" href="https://server/api/vApp/vapp-#####/metadata" type="application/vnd.vmware.vcloud.metadata+xml"/>
    <Link rel="ovf" href="https://server/api/vApp/vapp-#####/ovf" type="text/xml"/>
    <Link rel="down" href="https://server/api/vApp/vapp-#####/productSections/" type="application/vnd.vmware.vcloud.productSections+xml"/>
    <Description>Test vAPP</Description>
    <Tasks>
        <Task cancelRequested="false" expiryTime="2017-07-30T11:02:07.457+08:00" operation="Importing Virtual Application Test vAPP(#####)" operationName="vdcUploadOvfContents" serviceNamespace="com.vmware.vcloud" startTime="2017-05-01T11:02:07.457+08:00" status="running" name="task" id="urn:vcloud:task:######" href="https://server/api/task/####" type="application/vnd.vmware.vcloud.task+xml">
            <Link rel="task:cancel" href="https://server/api/task/#####/action/cancel"/>
            <Owner href="https://server/api/vApp/vapp-#####" name="Test vAPP" type="application/vnd.vmware.vcloud.vApp+xml"/>
            <User href="https://server/api/admin/user/####" name="#####" type="application/vnd.vmware.admin.user+xml"/>
            <Organization href="https://server/api/org/#####" name="#####" type="application/vnd.vmware.vcloud.org+xml"/>
            <Progress>1</Progress>
            <Details/>
        </Task>
    </Tasks>
    <Files>
        <File bytesTransferred="0" size="-1" name="descriptor.ovf">
            <Link rel="upload:default" href="https://server/transfer/#####/descriptor.ovf"/>
        </File>
    </Files>
    <DateCreated>2017-05-01T11:02:07.417+08:00</DateCreated>
    <Owner type="application/vnd.vmware.vcloud.owner+xml">
        <User href="https://server/api/admin/user/#####" name="#####" type="application/vnd.vmware.admin.user+xml"/>
    </Owner>
    <InMaintenanceMode>false</InMaintenanceMode>
</VApp>

【问题讨论】:

    标签: xml vb.net xpath


    【解决方案1】:

    首先加载你的文件,如果你使用XElement你可以使用文字来测试。

        'Dim yourpath As String = "your path here"
        Dim xe As XElement
        'to load from a file
        'xe = XElement.Load(yourpath)
    
        'for testing
        xe = <VApp href="https://#####/api/vApp/vapp-##">
                 <Link rel="down"/>
                 <Description>Test vAPP</Description>
                 <Tasks>
                     <Task cancelRequested="false">
                         <Link rel="task:cancel"/>
                         <Progress>1</Progress>
                         <Details/>
                     </Task>
                 </Tasks>
                 <Files>
                     <File bytesTransferred="0" size="-1" name="descriptor.ovf">
                         <Link rel="upload:default" href="https://server/transfer/descriptor.ovf"/>
                     </File>
                 </Files>
                 <InMaintenanceMode>false</InMaintenanceMode>
             </VApp>
    
    
        ' to save file
        ' xe.Save(yourpath)
    

    现在它已加载,很容易选择您想要的元素

    已编辑

        Dim dovf As IEnumerable = (From el In xe...<Files>
                                   Where el.<File>.@name = "descriptor.ovf"
                                   Select el.<File>.<Link>.@href)
    
        For Each s As String In dovf
            Stop
        Next
    

    基于上面的整个 xml 示例,我必须将其添加为程序的第一行

    Imports <xmlns="http://www.vmware.com/vcloud/v1.5">
    

    【讨论】:

    • 您好 dbasnett,感谢您的回复。我已经测试了代码,它看起来可以满足我的需要,但是当我将之前提供的示例(缩减 xml)替换为整个 XML 时,当我将 dovf 变量写入安慰。我已经更新了帖子以包含实际代码(敏感信息已散列)你能指出我出错的正确方向吗?
    【解决方案2】:

    Paste your xml as classes with Visual Studio。确保任何 xml 数组都有多个项目,以便正确生成架构。这是我的结果:

    '''<remarks/>
    <System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True), _
     System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)> _
    Partial Public Class VApp
    
        Private linkField As VAppLink
    
        Private descriptionField As String
    
        Private tasksField() As VAppTask
    
        Private filesField() As VAppFile
    
        Private inMaintenanceModeField As Boolean
    
        Private hrefField As String
    
        '''<remarks/>
        Public Property Link() As VAppLink
            Get
                Return Me.linkField
            End Get
            Set(value As VAppLink)
                Me.linkField = value
            End Set
        End Property
    
        '''<remarks/>
        Public Property Description() As String
            Get
                Return Me.descriptionField
            End Get
            Set(value As String)
                Me.descriptionField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlArrayItemAttribute("Task", IsNullable:=False)> _
        Public Property Tasks() As VAppTask()
            Get
                Return Me.tasksField
            End Get
            Set(value As VAppTask())
                Me.tasksField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlArrayItemAttribute("File", IsNullable:=False)> _
        Public Property Files() As VAppFile()
            Get
                Return Me.filesField
            End Get
            Set(value As VAppFile())
                Me.filesField = value
            End Set
        End Property
    
        '''<remarks/>
        Public Property InMaintenanceMode() As Boolean
            Get
                Return Me.inMaintenanceModeField
            End Get
            Set(value As Boolean)
                Me.inMaintenanceModeField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property href() As String
            Get
                Return Me.hrefField
            End Get
            Set(value As String)
                Me.hrefField = value
            End Set
        End Property
    End Class
    
    '''<remarks/>
    <System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
    Partial Public Class VAppLink
    
        Private relField As String
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property rel() As String
            Get
                Return Me.relField
            End Get
            Set(value As String)
                Me.relField = value
            End Set
        End Property
    End Class
    
    '''<remarks/>
    <System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
    Partial Public Class VAppTask
    
        Private linkField As VAppTaskLink
    
        Private progressField As Byte
    
        Private detailsField As Object
    
        Private cancelRequestedField As Boolean
    
        '''<remarks/>
        Public Property Link() As VAppTaskLink
            Get
                Return Me.linkField
            End Get
            Set(value As VAppTaskLink)
                Me.linkField = value
            End Set
        End Property
    
        '''<remarks/>
        Public Property Progress() As Byte
            Get
                Return Me.progressField
            End Get
            Set(value As Byte)
                Me.progressField = value
            End Set
        End Property
    
        '''<remarks/>
        Public Property Details() As Object
            Get
                Return Me.detailsField
            End Get
            Set(value As Object)
                Me.detailsField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property cancelRequested() As Boolean
            Get
                Return Me.cancelRequestedField
            End Get
            Set(value As Boolean)
                Me.cancelRequestedField = value
            End Set
        End Property
    End Class
    
    '''<remarks/>
    <System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
    Partial Public Class VAppTaskLink
    
        Private relField As String
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property rel() As String
            Get
                Return Me.relField
            End Get
            Set(value As String)
                Me.relField = value
            End Set
        End Property
    End Class
    
    '''<remarks/>
    <System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
    Partial Public Class VAppFile
    
        Private linkField As VAppFileLink
    
        Private bytesTransferredField As Byte
    
        Private sizeField As SByte
    
        Private nameField As String
    
        '''<remarks/>
        Public Property Link() As VAppFileLink
            Get
                Return Me.linkField
            End Get
            Set(value As VAppFileLink)
                Me.linkField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property bytesTransferred() As Byte
            Get
                Return Me.bytesTransferredField
            End Get
            Set(value As Byte)
                Me.bytesTransferredField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property size() As SByte
            Get
                Return Me.sizeField
            End Get
            Set(value As SByte)
                Me.sizeField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property name() As String
            Get
                Return Me.nameField
            End Get
            Set(value As String)
                Me.nameField = value
            End Set
        End Property
    End Class
    
    '''<remarks/>
    <System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
    Partial Public Class VAppFileLink
    
        Private relField As String
    
        Private hrefField As String
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property rel() As String
            Get
                Return Me.relField
            End Get
            Set(value As String)
                Me.relField = value
            End Set
        End Property
    
        '''<remarks/>
        <System.Xml.Serialization.XmlAttributeAttribute()> _
        Public Property href() As String
            Get
                Return Me.hrefField
            End Get
            Set(value As String)
                Me.hrefField = value
            End Set
        End Property
    End Class
    

    然后将 xml 反序列化为这些类。使用 LINQ 查找带有 name = "descriptor.ovf" 的唯一*元素。根据需要添加异常处理。

    Sub Main()
        Dim myVApp As VApp
        Dim serializer As New XmlSerializer(GetType(VApp))
        Using sr As New StreamReader("XMLFile1.xml")
            myVApp = CType(serializer.Deserialize(sr), VApp)
        End Using
        Dim href = myVApp.Files.Single(Function(f) f.name = "descriptor.ovf").Link.href
        Console.WriteLine(href)
        Console.ReadLine()
    End Sub
    

    输出:

    https://server/transfer/descriptor.ovf

    *您可以使用 SingleWhereFirst 与相同的谓词分别返回唯一的项目、所有项目或具有该名称的第一个项目。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-07
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多