从元素vb.net中的单个xml属性中收集值

时间:2017-05-01 12:32:35

标签: xml vb.net xpath

我一直在努力研究如何让这项工作工作几天(我已经结束了再次观看相同文章的循环,因为你已经搜索了这么多组合问题)

我看过Read XML in VB.netHow to read an XML File以及How to read XML elements in VB.NETRetrieve single attribute value from an xml doc element其中最后一个似乎指向了我关于正确方向的回合,但在运行DWRoelands指定的代码后,我收到了"系统.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>
&#13;
&#13;
&#13;

整个XML:

&#13;
&#13;
<?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>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:0)

首先加载文件,如果使用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">

答案 1 :(得分:0)

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与同一谓词一起使用,以分别返回唯一的项目,所有项目或具有该名称的第一项。