【问题标题】:VB.Net, XPath and XMLReader - Next and Previous recordsVB.Net、XPath 和 XMLReader - 下一条和上一条记录
【发布时间】:2015-07-10 04:25:20
【问题描述】:

下面的 VB.Net 代码可以很好地移动到 xml 文件 (sampler_01.xml) 中的下一条记录。如您所见,VB.Net 代码使用 XPath。我遇到的问题是让任何逻辑都可以使用“上一个”按钮 (btnPrevious) 并获取上一个记录。

我真正想做的是能够移到一条记录旁边或移回上一条记录。在这一点上,我不确定需要如何应用逻辑。任何建议或帮助将不胜感激。

谢谢!

编辑:请在下面使用“Form1.vb 2.0”查看我的更新答案

“sampler_01.xml”

<?xml version="1.0" encoding="UTF-8"?>
<Companies>
    <Company Id="000001">
        <CompID>000001</CompID>
        <ContFn>Jerry</ContFn>
        <ContLn>McGuire</ContLn>
        <ContEmail>jerrym@email.com</ContEmail>
        <ContPhone>(603) 555-1212</ContPhone>
    </Company>
    <Company Id="000002">
        <CompID>000002</CompID>
        <ContFn>Ben</ContFn>
        <ContLn>Henderson</ContLn>
        <ContEmail>benh@email.com</ContEmail>
        <ContPhone>(603) 882-4040</ContPhone>
    </Company>
    <Company Id="000003">
        <CompID>000003</CompID>
        <ContFn>Bob</ContFn>
        <ContLn>James</ContLn>
        <ContEmail>bobj@email.com</ContEmail>
        <ContPhone>(603) 641-2120</ContPhone>
    </Company>
    <Company Id="000004">
        <CompID>000004</CompID>
        <ContFn>Aaron</ContFn>
        <ContLn>Smith</ContLn>
        <ContEmail>arrons@email.com</ContEmail>
        <ContPhone>(603) 968-1212</ContPhone>
    </Company>
</Companies>

“Form1.vb 1.0”

Imports System.Net
Imports System.IO
Imports System.Xml
Imports System.Xml.XPath

  Public Class Form1

  Dim xpd As XPathDocument
  Dim xpn As XPathNavigator
  Dim xpn1, xpn2, xpn3, xpn4, xpn5 As XPathNodeIterator

  Private Sub Form1_Load(sender As System.Object, e As System.EventArgs)   Handles MyBase.Load

    LoadXmlToRead()

  End Sub

  Private Sub ListToTextBoxes()

    txtCompID.Text = xpn1.Current.Value
    txtContFn.Text = xpn2.Current.Value
    txtContLn.Text = xpn3.Current.Value
    txtContEmail.Text = xpn4.Current.Value
    txtContPhone.Text = xpn5.Current.Value

  End Sub

  Private Sub LoadXmlToRead()

    xpd = New XPathDocument("C:\XML_Files\sampler_01.xml")
    xpn = xpd.CreateNavigator()

    xpn1 = xpn.Select("/Companies/Company/CompID")
    xpn2 = xpn.Select("/Companies/Company/ContFn")
    xpn3 = xpn.Select("/Companies/Company/ContLn")
    xpn4 = xpn.Select("/Companies/Company/ContEmail")
    xpn5 = xpn.Select("/Companies/Company/ContPhone")

  End Sub

  Private Sub btnNext_Click(sender As System.Object, e As System.EventArgs) Handles btnNext.Click

    If xpn1.MoveNext() Or _
       xpn2.MoveNext() Or _
       xpn3.MoveNext() Or _
       xpn4.MoveNext() Or _
       xpn5.MoveNext() Then
       ListToTextBoxes()
    Else

    MsgBox("End of contacts has been reached...")
      LoadXmlToRead()
    End If

  End Sub

  Private Sub btnLoad_Click(sender As System.Object, e As  System.EventArgs)Handles btnLoad.Click

    LoadXmlToRead()

    If txtCompID.Text = "" And _
       txtContFn.Text = "" And _
       txtContLn.Text = "" And _
       txtContLn.Text = "" And _
       txtContPhone.Text = "" Then

       xpn1.MoveNext()
       xpn2.MoveNext()
       xpn3.MoveNext()
       xpn4.MoveNext()
       xpn5.MoveNext()

       ListToTextBoxes()

       MsgBox("The Contact database has been loaded")
    End If

  End Sub

  Private Sub btnPrevious_Click(sender As System.Object, e As System.EventArgs) Handles btnPrevious.Click

    If xpn1.Current.MoveToPrevious() Or _
       xpn2.Current.MoveToPrevious() Or _
       xpn3.Current.MoveToPrevious() Or _
       xpn4.Current.MoveToPrevious() Or _
       xpn5.Current.MoveToPrevious() Then

       ListToTextBoxes()

    End If

  End Sub
End Class

【问题讨论】:

  • 您是否有特定的理由不只是将 XML 数据加载到某种形式的集合中并直接使用它,而不是尝试连续处理 XML?
  • 感谢达米安的回复。我在这些实例上加载 XML 的原因是我可以捕获任何更新。上面的代码我已经分解成更简单的格式,以便其他人可以在本地级别进行采样,但它实际上是从远程服务器读取 XML。但是,我真的看不出它是如何持续对 XML 起作用的?
  • 您好 Damien - 顺便说一下,我确实知道您的问题所在,但 XML 文件最多可以达到 3 MEG。 XML Reader 似乎工作得更快。如果您知道在不牺牲速度的情况下将其加载到集合中的方法,请随时指出我的方向。我唯一的其他想法是通过序列化,但我还没有到那一步来测试......再次感谢您的回复......
  • 嗨,Damien,感谢您的意见,因为这鼓励我更加努力地研究 XMLReader...我找到了我正在寻找的...最好的!

标签: xml vb.net xpath


【解决方案1】:

使用 XML linq

Imports System.Xml
Imports System.Xml.Linq
Public Class Form1

    Const FILENAME As String = "c:\temp\test.xml"

    Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Dim doc As XDocument = XDocument.Load(FILENAME)

        Dim companies = doc.Descendants("Company").ToList()

        Dim companyPointer = companies.First()

        Dim index As Integer = 0
        companyPointer = companies(index + 1)
        index = index + 1


    End Sub

End Class
​

【讨论】:

  • 您好 jdweng,感谢您的回复。稍后我将对此进行研究,看看我可以如何实现。
  • 您好,jdweng,感谢您的建议!我能够查看 Linq,并且在比较大型 XML 文件时,我发现 XML 阅读器是我需要的更好的选择。再次,非常感谢您抽出时间回复!最好的!
  • 您的意思是将xml反序列化为类吗?还是一次只阅读一家公司?对于巨大的 xml,建议使用 XML 阅读器以获得最佳性能。如果您要多次搜索 xml,那么最好将整个 xml 读入类(反序列化)或像 Virtual Storm 建议的数据表中。我喜欢数据表方法并且经常使用它。在一条指令中,您可以阅读整个文件。然后在数据表上使用 Linq 执行查询。
【解决方案2】:

下面使用 XML Reader 的代码可以有效地满足我的需要。在对 Linq 进行了一些测试之后(正如 jdweng 雄辩地建议的那样),我发现 XML Reader 在经过重新设计后是读取超过 1MEG 的更大 XML 文件的更好选择。下面的代码在读取 XML 文件时捕获任何更新,同时处理上一个和下一个控件。

“Form1.vb 2.0”

Imports System.IO
Imports System.Xml

Public Class Form1

      Public dSet = New DataSet
      Public CompRow As Integer

      Private Sub FileLoad()

          dSet.Clear()

          Dim xmlFile As XmlReader
          xmlFile = XmlReader.Create("C:\XML_Files\sampler_01.xml", New XmlReaderSettings())
          dSet.ReadXml(xmlFile)

          CompRow = 0
          ShowData(CompRow)

          xmlFile.Close()

      End Sub

      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

          FileLoad()

      End Sub

      Private Sub btnReLoad_Click(sender As System.Object, e As System.EventArgs) Handles btnReLoad.Click

          FileLoad()

      End Sub

      Private Sub ShowData(ByVal CurrentRow)

          txtCompID.Text = dSet.Tables("Company").Rows(CompRow)("CompID").ToString
          txtContFn.Text = dSet.Tables("Company").Rows(CompRow)("ContFn").ToString
          txtContLn.Text = dSet.Tables("Company").Rows(CompRow)("ContLn").ToString
          txtContEmail.Text = dSet.Tables("Company").Rows(CompRow)("ContEmail").ToString
          txtContPhone.Text = dSet.Tables("Company").Rows(CompRow)("ContPhone").ToString

      End Sub

      Private Sub btnNext_Click(sender As System.Object, e As System.EventArgs) Handles btnNext.Click

          If CompRow <> dSet.Tables("Company").Rows.Count - 1 Then
              CompRow += 1
              ShowData(CompRow)
          Else
              MsgBox("Last Record is Reached!!!")
          End If

      End Sub

      Private Sub btnPrevious_Click(sender As System.Object, e As System.EventArgs) Handles btnPrevious.Click

          If CompRow <> 0 Then
              CompRow -= 1
              ShowData(CompRow)
          Else
              MsgBox("First Record is Reached!!!")
          End If

      End Sub
End Class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 2015-10-13
    • 1970-01-01
    • 2015-09-12
    相关资源
    最近更新 更多