You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历XML文档时如何获取指定节点下的Object元素列表?

问题描述

我正在处理XML文档的遍历操作,示例XML如下:

<DOCUMENT_ELEMENT FormName="Form Name">
  <Object type="Form" name="form1">
    <Object type="BaseDesignPanel" name="Panel1">
      <Object type="FormsLabel" name="Label9">
        <Property name="BackColor">White</Property>
        <Property name="Name">Label9</Property>
        <Property name="Size">76, 16</Property>
        <Property name="Text">Page 1 of 3</Property>
        <Property name="Location">723, 985</Property>
      </Object>
      <Property name="AutoScrollMargin">800, 3000</Property>
      <Property name="IsWriteProtected">False</Property>
      <Property name="TabIndex">0</Property>
      <Property name="Size">800, 3000</Property>
      <Property name="Pages">3</Property>
      <Property name="BackColor">White</Property>
      <Property name="Tag">Please do not delete</Property>
      <Property name="Location">0, 0</Property>
      <Property name="AutoScrollMinSize">800, 3000</Property>
      <Property name="Name">Panel1</Property>
      <Property name="BackgroundImageLayout">None</Property>
    </Object>
    <Property name="MaximumSize">833, 1033</Property>
    <Property name="Name">form1</Property>
    <Property name="AutoScroll">True</Property>
    <Property name="ClientSize">817, 730</Property>
  </Object>
</DOCUMENT_ELEMENT>

我使用以下递归代码遍历每个节点:

Private Sub XmlDocumentWalker(XmlNode As XmlNode)
        If TypeOf XmlNode Is XmlComment Then
            Console.WriteLine("XML Comment:" + XmlNode.Value)
            If XmlNode.HasChildNodes Then XmlDocumentWalker(XmlNode.FirstChild)
            If Not IsNothing(XmlNode.NextSibling) Then XmlDocumentWalker(XmlNode.NextSibling)
        ElseIf TypeOf XmlNode Is XmlElement Then
            If XmlNode.HasChildNodes And (TypeOf XmlNode.FirstChild Is XmlText) Then
                Console.WriteLine("XML Element:" + XmlNode.Name & "=""" & XmlNode.FirstChild.Value & """")
            Else
                Console.WriteLine("XML Element: " + XmlNode.Name)
            End If
            If DirectCast(XmlNode, XmlElement).HasAttributes Then
                For Each XmlAttribute As XmlNode In DirectCast(XmlNode, XmlElement).Attributes
                    Console.WriteLine("XML Attribute: " + XmlAttribute.Name & "=""" & XmlAttribute.Value & """")
                Next
            End If

            If XmlNode.HasChildNodes And Not (TypeOf XmlNode.FirstChild Is XmlText) Then XmlDocumentWalker(XmlNode.FirstChild)
            If Not IsNothing(XmlNode.NextSibling) Then XmlDocumentWalker(XmlNode.NextSibling)
        End If
    End Sub

现在需要实现:当遍历到Panel1节点时,获取该节点下的所有Object元素列表。

解决方案

可以通过以下几种方式实现需求:

方法1:修改现有递归遍历代码

在递归过程中,判断当前节点是否是目标Panel1节点,然后收集其下的所有Object子节点:

' 定义列表用于存储目标Object节点
Private targetObjects As List(Of XmlNode) = New List(Of XmlNode)()

Private Sub XmlDocumentWalker(XmlNode As XmlNode)
    If TypeOf XmlNode Is XmlComment Then
        Console.WriteLine("XML Comment:" + XmlNode.Value)
        If XmlNode.HasChildNodes Then XmlDocumentWalker(XmlNode.FirstChild)
        If Not IsNothing(XmlNode.NextSibling) Then XmlDocumentWalker(XmlNode.NextSibling)
    ElseIf TypeOf XmlNode Is XmlElement Then
        Dim elem As XmlElement = DirectCast(XmlNode, XmlElement)
        ' 检查当前节点是否是Panel1
        If elem.Name = "Object" AndAlso elem.GetAttribute("name") = "Panel1" Then
            ' 收集该节点下所有Object子节点
            For Each childNode As XmlNode In elem.ChildNodes
                If TypeOf childNode Is XmlElement AndAlso childNode.Name = "Object" Then
                    targetObjects.Add(childNode)
                End If
            Next
            ' 输出收集到的节点信息
            Console.WriteLine($"找到Panel1下的{targetObjects.Count}个Object节点:")
            For Each objNode As XmlNode In targetObjects
                Dim objElem As XmlElement = DirectCast(objNode, XmlElement)
                Console.WriteLine($"Object type={objElem.GetAttribute("type")}, name={objElem.GetAttribute("name")}")
            Next
        End If

        ' 原有的遍历输出逻辑
        If XmlNode.HasChildNodes And (TypeOf XmlNode.FirstChild Is XmlText) Then
            Console.WriteLine("XML Element:" + XmlNode.Name & "=""" & XmlNode.FirstChild.Value & """")
        Else
            Console.WriteLine("XML Element: " + XmlNode.Name)
        End If
        If elem.HasAttributes Then
            For Each XmlAttribute As XmlNode In elem.Attributes
                Console.WriteLine("XML Attribute: " + XmlAttribute.Name & "=""" & XmlAttribute.Value & """")
            Next
        End If

        If XmlNode.HasChildNodes And Not (TypeOf XmlNode.FirstChild Is XmlText) Then XmlDocumentWalker(XmlNode.FirstChild)
        If Not IsNothing(XmlNode.NextSibling) Then XmlDocumentWalker(XmlNode.NextSibling)
    End If
End Sub

方法2:使用XPath直接查询

如果不需要完整遍历整个文档,直接用XPath定位到Panel1节点,再查询其下的Object元素会更高效:

' 假设xmlDoc是已加载的XmlDocument对象
Dim panel1Node As XmlNode = xmlDoc.SelectSingleNode("//Object[@name='Panel1']")
If panel1Node IsNot Nothing Then
    Dim objectNodes As XmlNodeList = panel1Node.SelectNodes("./Object")
    Console.WriteLine($"找到Panel1下的{objectNodes.Count}个Object节点:")
    For Each objNode As XmlNode In objectNodes
        Dim objElem As XmlElement = DirectCast(objNode, XmlElement)
        Console.WriteLine($"Object type={objElem.GetAttribute("type")}, name={objElem.GetAttribute("name")}")
    Next
End If

方法3:使用LINQ to XML(更简洁)

如果使用XDocument而非XmlDocument,可以用LINQ查询实现:

' 假设xd是已加载的XDocument对象
Dim panel1Object = xd.Descendants("Object").FirstOrDefault(Function(o) o.Attribute("name")?.Value = "Panel1")
If panel1Object IsNot Nothing Then
    Dim childObjects = panel1Object.Elements("Object").ToList()
    Console.WriteLine($"找到Panel1下的{childObjects.Count}个Object节点:")
    For Each obj In childObjects
        Console.WriteLine($"Object type={obj.Attribute("type")?.Value}, name={obj.Attribute("name")?.Value}")
    Next
End If

内容的提问来源于stack exchange,提问作者Peter Sun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 13:16:01