使用VB.Net读取和写入xml文件

时间:2013-03-28 12:07:53

标签: vb.net xml-parsing

我对编程世界很陌生(我是一个网络人)。然而,我被要求开发一个前端,为控制台应用程序配置xml文件。控制台应用程序从此xml文件中读取并打开浏览器的多个实例,每个监视器一个实例(总共6个监视器)。有4个控制中心,每个控制中心有6个监视器。每个控制中心都使用单独的电脑运行。这些电脑不在网络上,无法相互访问。我被告知我也不能使用数据库。

每个监视器一次显示一个网站,可能会有多个网站列出要在特定监视器上显示,因此它们会定期更改。每个控制中心将显示不同的站点。

我的第一个问题:这个XML有效吗?

<ControlCenter>
  <Monitor>
      <monitor_id>0</monitor_id>
      <browser_short_na>ie</browser_short_na>
  <url_list>
    <url>
    <url_id>0</url_id>
    <url_na><![CDATA[http://www.hmv.com]]></url_na>
         <parameter><![CDATA[]]></parameter>
    </url>
    <url>
    <url_id>1</url_id>
    <url_na><![CDATA[http://www.amazon.com]]></url_na>
         <parameter><![CDATA[]]></parameter>
    </url>
    <url>
    <url_id>2</url_id>
    <url_na><![CDATA[http://www.google.com]]></url_na>
         <parameter><![CDATA[]]></parameter>
    </url>
 </url_list>
   </Monitor>
   <Monitor>
   <monitor_id>1</monitor_id>
   <browser_short_na>ie</browser_short_na>
    <url_list>
    <url>
            <url_id>0</url_id>
            <url_na><![CDATA[http://www.amazon.com]]></url_na>
            <parameter><![CDATA[]]></parameter>
    </url>
    </url_list>
   </Monitor>
</ControlCenter>

到目前为止我所做的是打开xml文件并将所有显示器添加到组合框

 Dim dom As New Xml.XmlDocument
    dom.Load("test.xml")
    ComboBox1.Items.Clear()
    Dim monitorid As String = String.Empty
    For Each node As Xml.XmlNode In  dom.SelectNodes("//ControlCenter/Monitor/monitor_id")
        monitorid = node.InnerText
        ComboBox1.Items.Add(monitorid)
    Next

这就是我被困住的地方。一旦用户从组合框中选择一个监视器,我就需要获得该监视器的所有信息。所以我需要browser_short_na,并且所有的网址都基于所选的monitor_id。

我尝试过创建数据集,使用readxml加载xmlfile。然后我尝试创建指向该数据集的数据视图。尝试将RowFilter添加到数据视图。

Dim val As String = ComboBox1.SelectedItem.ToString

    Dim dsXmlFile As New DataSet
    dsXmlFile.ReadXml("test.xml")

Dim dv As New DataView
    dv.Table = dsXmlFile.Tables(0)

    Dim drv As DataRowView
    dv.RowFilter = "monitor_id = " & val

Dim url As String = ""
    'Retrieve my values returned in the result
    For Each drv In dv
        url = drv("url_na")
    Next

当我单步执行代码并查看for循环时,它会失败,并显示消息“url_na既不是DataColumn也不是Table Monitor的DataRelation。”

我在想我没有正确处理url_list部分。

一旦读取了所选监视器的所有信息,我将在文本框/列表框中显示值,然后用户可以编辑这些值。如果他们然后保存它应该将新值写入xml文件。他们还可以选择在列表中添加其他网址,甚至可以创建一个全新的监控部分。

非常感谢任何帮助/建议。

2 个答案:

答案 0 :(得分:0)

您应该使用XPath来解析XML文档。

  • 在XMLDocument中加载xml文件
  • 创建XMLNodeList并使用XPath从加载的xml中选择节点 文档。
  • 然后解析节点列表并提取所选监视器的所有信息
    节点基于id。

以下是对您有帮助的XPath表达式:

  1. 从文件中选择监控节点:“ / ControlCenter / Monitor
  2. 根据监视器ID选择browser_na字段:“ / ControlCenter / Monitor [monitor_id ='0'] / browser_short_na
  3. 根据监视器ID选择网址:“ / ControlCenter / Monitor [monitor_id ='0'] / url_list / url / url_na
  4. 希望它适合你。

答案 1 :(得分:0)

我会反过来解决你的问题:

  1. 定义一个包含所需数据的类(或几个类)。
  2. 使用简单的序列化程序从/向该文件加载/保存。
  3. 如果您这样做,那么您选择的问题只是一个经典的WPF问题。

    Public Class Monitor
        Public Property MonitorId As integer
        Public Property ListOfUrl As List(Of String)
    End Class
    
    然后

    MonitorsConfiguration将引用List(Of Monitor)对象。

    您可以使用ViewModel对象轻松处理MonitorsConfigurationViewModel具有SelectedMonitorIndex属性,并在索引属性更改时更新UrlForThisMonitor网址列表。
    (显然它应该实现INotifyPropertyChanged

    好的,可以看看ViewModel的样子:

    Public Class MonitorsConfigurationVM
           Implement INotifyPropertyChanged
    
       ' creates a new VM. Throws exception if file name is not valid 
       Public Sub New(ConfigFileName As String)
          _FileName = ConfigFileName
          _MonitorsConfiguration = // Deserialization of the file //
          _MonitorIndex = 0 
       End Sub
    
      Public Property MonitorIndex As integer
       Get
         return _MonitorIndex
       End Get
       Set (Value)
         if (_MonitorIndex = value) then return
         ' you might want to perform check here and allow only valid index
         _MonitorIndex = value
         _UrlIndex=0
         NotifyPropertyChanged("MonitorIndex")
         NotifyPropertyChanged("MonitorUrls")
         NotifyPropertyChanged("HasUrl")
         NotifyPropertyChanged("UrlIndex")
       End Set
      End Property
    
      Public ReadOnly Property HasUrl As Boolean  
       Get
          return Not (MonitorUrls Is Nothing OrElse MonitorUrls.count = 0 )
          ' ( might be used to disable the listbox bound to MonitorUrl )
       End Get
      End Property
    
      Public ReadOnly Property MonitorUrls As List(Of String)
      Get
        return _MonitorConfiguration(_MonitorIndex).ListOfUrl  '(you might want to chk)
      End Get
      End Property
    
      Public Property UrlIndex As Integer 
      Get
         return _UrlIndex
      End Get
      Set (value)
        if value = _UrlIndex then return
        ' you might want to perform some check here
        _UrlIndex = value
        NotifyPropertyChanged("UrlIndex")
      End Set
      End Property
    
     ' And Also : AddMonitor  /   AddUrl  /  SaveConfiguration / ...
    
      Private _FileName As String = Nothing
      Private _MonitorsConfiguration As List(Of Monitor)=Nothing
      Private _MonitorIndex As integer = 0
    
       Protected Sub NotifyPropertyChanged(ByVal name As String)
           RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
       End Sub
    
       Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    
    End Class