【问题标题】:Iterating through XML using XPathNavigator and XPathNodeIterator使用 XPathNavigator 和 XPathNodeIterator 遍历 XML
【发布时间】:2015-03-13 15:40:48
【问题描述】:

我正在做一个项目,我接受一个 XML 文件并且需要遍历 XML 并输出特定节点的文本值,我正在努力寻找最好的方法来做到这一点。

我正在使用以下代码,它适用于我定义的单个 XPath 节点,它工作正常,但我需要提取其他节点及其相关文本。任何指向正确方向的指针将不胜感激。我一直在阅读来自 Microsoft 的 XPathNavigatorXPathNodeIteratorXMLReader 文档并使用他们的示例,但似乎没有一个适合这个特定的用例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.XPath;
namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            XPathDocument document = new XPathDocument("Security_Policy.xml");
            XPathNavigator navigator = document.CreateNavigator();
            XPathNodeIterator nodes = navigator.Select("//Rule_Number");
            while (nodes.MoveNext())
            {
                Console.WriteLine(nodes.Current.Value);
            }
        }
    }
}

这是我正在使用的相关 XML 块。

<?xml version="1.0" encoding="utf-8"?>
      <rule>
        <Name></Name>
        <Class_Name>security_rule</Class_Name>
        <Rule_UUID>{9BA1463A-00D0-4819-88B6-650407733A96}</Rule_UUID>
        <Rule_Number>1</Rule_Number>
        <action>
          <action>
            <Name>accept</Name>
            <Class_Name>accept_action</Class_Name>
            <action><![CDATA[]]></action>
            <identity_settings>
              <Name></Name>
              <Class_Name>identity_action_settings</Class_Name>
              <allow_ad_query>true</allow_ad_query>
              <allow_captive_portal>true</allow_captive_portal>
              <allow_identity_agent>true</allow_identity_agent>
              <allowed_sources><![CDATA[All Sources]]></allowed_sources>
              <redirect_to_captive_portal>false</redirect_to_captive_portal>
              <require_packet_tagging>false</require_packet_tagging>
              <type><![CDATA[identity_action_settings]]></type>
            </identity_settings>
            <macro><![CDATA[RECORD_CONN]]></macro>
            <type><![CDATA[accept]]></type>
          </action>
        </action>
        <comments><![CDATA[]]></comments>
        <disabled>false</disabled>
        <dst>
          <Name></Name>
          <Class_Name>rule_destination</Class_Name>
          <members>
            <reference>
              <Name></Name>
              <Table>network_objects</Table>
            </reference>
            <reference>
              <Name></Name>
              <Table>network_objects</Table>
            </reference>
          </members>
          <compound></compound>
          <op><![CDATA[]]></op>
        </dst>
        <global_location><![CDATA[middle]]></global_location>
        <install>
          <Name></Name>
          <Class_Name>rule_install</Class_Name>
          <members>
            <reference>
              <Name>Any</Name>
              <Table>globals</Table>
            </reference>
          </members>
          <compound></compound>
        </install>
        <name><![CDATA[]]></name>
        <services>
          <Name></Name>
          <Class_Name>rule_services</Class_Name>
          <members>
            <reference>
              <Name>Any</Name>
              <Table>globals</Table>
            </reference>
          </members>
          <compound></compound>
          <op><![CDATA[]]></op>
        </services>
        <src>
          <Name></Name>
          <Class_Name>rule_source</Class_Name>
          <members>
            <reference>
              <Name></Name>
              <Table>network_objects</Table>
            </reference>
            <reference>
              <Name></Name>
              <Table>network_objects</Table>
            </reference>
          </members>
          <compound></compound>
          <op><![CDATA[]]></op>
        </src>
        <through>
          <Name></Name>
          <Class_Name>rule_vpn</Class_Name>
          <members>
            <reference>
              <Name>Any</Name>
              <Table>globals</Table>
            </reference>
          </members>
          <compound></compound>
        </through>
        <time>
          <time>
            <Name>Any</Name>
            <Table>globals</Table>
          </time>
        </time>
        <track>
          <track>
            <Name>Log</Name>
            <Table>tracks</Table>
          </track>
        </track>
      </rule>

【问题讨论】:

  • Linq to XML 可能是最容易使用的。你能具体告诉我们你想要什么输出吗?您当前的代码显示了哪些有效,而不是哪些无效。

标签: c# xml xpath


【解决方案1】:

我认为您的 XPath 路径不正确,因为“Rule_Number”元素不是文档的根,但是我不是 XPath 专家,因此请采纳以下 XPath 建议:

//rule/Rule_Number

这是另一种方法,因为我大力提倡尽可能使用 linq-to-xml,因为它使用起来非常直观:

XDocument doc = XDocument.Load("Security_Policy.xml");
var ruleNodes = doc.Root.Elements("Rule_Number");
foreach(var node in ruleNodes)
{
    Console.WriteLine(node.Value);
}

编辑:

如果您想要元素而不管 XML 文档的层次结构中的哪个位置,您都可以使用 doc.Descendants("TAG NAME") 来获取具有匹配“标签名称”的任何内容(从技术上讲,该字段中的数据是 XName,但不要暂时不用担心)。

【讨论】:

  • 正要提出这个建议。使用起来更容易,而且速度也很快。
  • 是的,我个人不是 XPath 的忠实粉丝。当然有它的位置,但是使用像 LINQ 这样的新的遍历 XML 的方法让生活变得更加轻松。
  • 感谢大家,我正在研究 linq to xml。我首先来自 perl 和 php,因此了解可用于此类事物的内置方法很有趣。使用上面的 sn-p 不会返回任何内容,但我确定这就是我定义 doc.Root.Elements 的方式。
  • 我上面的片段假设 是您文档的根目录。如果这不准确,您可能需要在我的代码片段中添加更多级别。看看 MSDN 的入门教程:msdn.microsoft.com/en-us/library/bb387061.aspx
  • 尝试使用 xdoc.Descendents("Rule_Number");而不是 Root.Elements
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 2023-04-06
  • 2021-11-12
  • 2019-07-07
  • 2016-03-08
相关资源
最近更新 更多