Reputation: 11
I'm working on a project where I accept an XML file and have a need to iterate through the XML and output the text values of specific nodes and I'm struggling with the best approach to doing this.
I'm using the following code which works for the single XPath node I've defined which works fine, but I need to extract additional nodes and their associated text. Any pointers in the right direction would be greatly appreciated. I've been reading through the XPathNavigator
, XPathNodeIterator
, XMLReader
documentation from Microsoft and using their examples, but none seem to fit this specific use case.
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);
}
}
}
}
Here is the relevant block of XML I'm working with.
<?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>
Upvotes: 1
Views: 856
Reputation: 7097
I believe that your XPath path is incorrect since the "Rule_Number" element isn't the root of the document, however I'm not an XPath expert so take the below XPath suggestion with a grain of salt:
//rule/Rule_Number
Here's another way to do it since I'm a big advocate of using linq-to-xml whenever possible since it's very intuitive to use:
XDocument doc = XDocument.Load("Security_Policy.xml");
var ruleNodes = doc.Root.Elements("Rule_Number");
foreach(var node in ruleNodes)
{
Console.WriteLine(node.Value);
}
EDIT:
If you want elements regardless of where in the hierarchy of the XML document, you can use doc.Descendants("TAG NAME")
to get anything with the matching "tag name" (technically the data is an XName
in that field, but don't worry about that for now).
Upvotes: 1