使用VB.Net读写XML文件

3
我是一个相对新手的程序员(我是网络工程师)。然而,我被要求开发一个前端来配置一个控制台应用程序的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

现在我遇到了困难。一旦用户从组合框中选择一个显示器,我就需要获取该显示器的所有信息。因此,我需要浏览器短名称和所有基于所选monitor_id的URL。

我尝试过创建数据集,并使用readxml加载xml文件。然后我尝试创建一个指向该数据集的数据视图。尝试向数据视图添加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

当我逐步执行代码并查看每个循环时,出现了错误消息:“url_na既不是DataColumn也不是表Monitor的DataRelation。”
我认为我没有正确处理url_list部分。
一旦读取所选监视器的所有信息,我将在文本框/列表框中显示值,用户可以编辑这些值。如果他们保存,则应将新值写入xml文件。他们还可以选择将其他网址添加到列表中,甚至创建一个全新的监视器部分。
非常感谢任何帮助/建议。
2个回答

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选择URL:“/ControlCenter/Monitor[monitor_id='0']/url_list/url/url_na

希望这对您有所帮助。


0
我会为您的问题提供另一种解决方案:
  1. 定义一个类(或多个类)来保存所需的数据。
  2. 使用简单的序列化程序从文件中加载/保存数据。
如果这样做,那么您在选择方面遇到的问题就只是经典的 WPF 问题。
Public Class Monitor
    Public Property MonitorId As integer
    Public Property ListOfUrl As List(Of String)
End Class

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

您可以使用 ViewModel 对象轻松处理 MonitorsConfiguration
ViewModel 具有 SelectedMonitorIndex 属性,并在索引属性更改时更新 UrlForThisMonitor url 列表。
(显然,它应该实现 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

不想成为那些人之一,但你能给我一个创建ViewModel对象的代码示例吗? - William
不确定您是否已经更新了编辑内容:顺便说一下,我已经编辑了我的帖子 :-) - GameAlchemist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接