使用XElement和.Element查询XML

使用XElement和.Element查询XML,xml,vb.net,Xml,Vb.net,为一个真正的初学者问题道歉;我对将VB与XML结合使用非常陌生,需要一些指导才能达到理解的临界值 给定以下描述各种糖果的XML: <?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <Candy ID="MnMs"> <Form ID="tablet" Name="Tablet"> <

为一个真正的初学者问题道歉;我对将VB与XML结合使用非常陌生,需要一些指导才能达到理解的临界值

给定以下描述各种糖果的XML:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <Candy ID="MnMs">
    <Form ID="tablet" Name="Tablet">
      <Component ID="shell" Ingredients="sugar"/>
      <Component ID="filling" Ingredients="chocolate"/>
    </Form>
    <Form ID="oblong">
      <Component ID="shell" Ingredients="sugar"/>
      <Component ID="filling" Ingredients="chocolate"/>
      <Component ID="center" Ingredients="nut"/>
    </Form>
  </Candy>
  <Candy ID="LBalls">
    <Form ID="sphere">
      <Component ID="shell" Ingredients="chocolate"/>
      <Component ID="filling" Ingredients="chocolate ganache"/>
    </Form>
  </Candy>
  <Candy ID="RPieces">
    <Form ID="tablet">
      <Component ID="shell" Ingredients="sugar"/>
      <Component ID="filling" Ingredients="peanut butter ganache"/>
    </Form>
  </Candy>
</xs:schema>
我的VB函数如下;我对如何管理身份感到困惑,特别是考虑到属性是
ID
ID

Imports System.IO
Imports System.Xml
...
Function CandyFetch(ByVal candyId As String, ByVal formId As String, ByVal compId As String, ByVal attrId As String, Optional ByVal docPath As String = "Candies.xml") As String
    Const ID = "ID"
    Dim result = ""
    docPath = docPath.Trim()
    If Not File.Exists(docPath) Then docPath = AppDomain.CurrentDomain.BaseDirectory + docPath
    For Each bonbon In XElement.Load(docPath).Elements("Candy")
        If bonbon.Attribute(ID).Value = candyId Then
            For Each form In bonbon.Elements("Form")
                If form.Attribute(ID).Value = formId Then
                    For Each component In form.Elements("Component")
                        If component.Attribute(ID).Value = compId Then
                            result = component.Attribute(attrId).Value
                            Exit For
                        End If
                    Next
                End If
            Next
        End If
    Next
    Return result
End Function
多谢各位


接着,有没有一种更简单的方法可以使用LinqToXml来实现这一点,而不必遍历XML元素?

我建议使用XPATH查询:

Dim filename As String = "C:\Junk\example.xml"
Dim xdc As New XmlDocument
xdc.Load(filename)
Dim nsm As New XmlNamespaceManager(xdc.NameTable)
nsm.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema")
Dim strXPATH As String = "/xs:schema/Candy[@ID=""RPieces""]/Form/Component[@ID=""filling""]/@Ingredients"
MsgBox(strXPATH & "=" & vbCrLf &
       xdc.DocumentElement.SelectSingleNode(strXPATH, nsm).InnerText)

我建议使用XPATH查询:

Dim filename As String = "C:\Junk\example.xml"
Dim xdc As New XmlDocument
xdc.Load(filename)
Dim nsm As New XmlNamespaceManager(xdc.NameTable)
nsm.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema")
Dim strXPATH As String = "/xs:schema/Candy[@ID=""RPieces""]/Form/Component[@ID=""filling""]/@Ingredients"
MsgBox(strXPATH & "=" & vbCrLf &
       xdc.DocumentElement.SelectSingleNode(strXPATH, nsm).InnerText)

使用LINQ到Xml,它可以如下所示

Dim doc As XDocument = XDocument.Load(docPath)
Dim value = doc.Descendants("Candy").
                Where(Function(candy) candy.Attribute("ID").Value = "RPieces").
                SelectMany(Function(candy) candy.Elements("Form")).
                Where(Function(form) form.Attribute("ID").Value = "tablet").
                SelectMany(Function(form) form.Elements("Component")).
                Where(Function(component) component.Attribute("ID").Value = "filling").
                Select(Function(component) component.Attribute("Ingredients").Value).
                FirstOrDefault()
通过使用具有Xml轴属性的LINQ to Xml,您可以使代码更简单。


使用LINQ到Xml,它可以如下所示

Dim doc As XDocument = XDocument.Load(docPath)
Dim value = doc.Descendants("Candy").
                Where(Function(candy) candy.Attribute("ID").Value = "RPieces").
                SelectMany(Function(candy) candy.Elements("Form")).
                Where(Function(form) form.Attribute("ID").Value = "tablet").
                SelectMany(Function(form) form.Elements("Component")).
                Where(Function(component) component.Attribute("ID").Value = "filling").
                Select(Function(component) component.Attribute("Ingredients").Value).
                FirstOrDefault()
通过使用具有Xml轴属性的LINQ to Xml,您可以使代码更简单。


还是个初学者,在这里。。。只需Dim strXML=File.ReadAllText(docPath)即可从外部文件加载文本。。。或者我应该使用XDocument.Load或类似的东西吗?您可以使用
XmlDocument.Load
来加载文件,而不是解析内存中的
字符串。我已经更新了我的答案,还是一个初学者,在这里。。。只需Dim strXML=File.ReadAllText(docPath)即可从外部文件加载文本。。。或者我应该使用XDocument.Load或类似的东西吗?您可以使用
XmlDocument.Load
来加载文件,而不是解析内存中的
字符串。我已经更新了我的答案
Dim serializer As New XmlSerializer(GetType(YourRootClass))
Dim data As YourRootClass = Nothing
Using fileStream As New FileStream(docPath, FileMode.Open)
    data = serializer.Deserialize(fileStream)
End Using

Dim value = data.Candies.
                 Where(Function(candy) candy.ID = "RPieces").
                 SelectMany(Function(candy) candy.Forms).
                 Where(Function(form) form.ID = "tablet").
                 SelectMany(Function(form) form.Components).
                 Where(Function(component) component.ID = "filling").
                 Select(Function(component) component.Ingredients).
                 FirstOrDefault()