Obtain XML child nodes using C#
Solution 1
Assuming the API reliably returns that XML structure you can simply specify the path to the node as "/entry/m:properties"
then call get children. After that you'll want to loop over those nodes, checking for the nodes you want.
Currently your foreach loop is attempting all of those operations on the <id></id>
node which causes an Exception because there is no "title" attribute.
So to give some sample code, you're looking for something like this;
XmlNode props = root.SelectSingleNode("/entry/m:properties");
for (int i = 0; i < props.ChildNodes.Count; i++)
{
if (propes.ChildNodes[i].Name = "node I want")
{
//do something
}
}
Or if you specifically only want those two values, then just use SelectSingleNode
with the full path to that node. From your question it sounds like there is no reason to use iteration. So you could simply do;
string accountName = root.SelectSingleNode("/entry/m:properties/d:Name").InnerXml;
to get the account name.
Solution 2
using Linq2Xml will probably be a little easier.
var xml = "<entry xmlns:m=\"ns1\" xmlns:n=\"ns2\" xmlns:d=\"ns3\">" +
"<id></id>" +
"<title type=\"text\"></title>" +
"<updated></updated>" +
"<author><name /></author>" +
"<link rel=\"edit\" title=\"Account\" href=\"AccountSet\" />" +
"<category term=\"Microsoft.Crm.Sdk.Data.Services.Account\" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\" />" +
"<content type=\"application/xml\">" +
"<m:properties>" +
"<d:neu_UniqueId></d:neu_UniqueId>" +
"<d:AccountId m:type=\"Edm.Guid\">Account ID</d:AccountId>" +
"<d:Name>Account Name</d:Name>" +
"</m:properties></content>" +
"</entry>";
const string namespaceM = "ns1";
const string namespaceD = "ns3";
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
using (var reader = XmlReader.Create(stream))
{
var document = XDocument.Load(reader, LoadOptions.None);
var contentNode = document.Elements().First().Elements().First(e => e.Name.LocalName == "content");
var propertiesNode = contentNode.Elements().First(d => d.Name.LocalName == "properties" && d.Name.Namespace == namespaceM);
var accountIdNode = propertiesNode.Elements().First(d => d.Name.LocalName == "AccountId" && d.Name.Namespace == namespaceD);
var nameNode = propertiesNode.Elements().First(d => d.Name.LocalName == "Name" && d.Name.Namespace == namespaceD);
var accountIdText = accountIdNode.Value;
var nameText = nameNode.Value;
}
}
NealR
Updated on April 25, 2020Comments
-
NealR about 4 years
This is my first time attempting to parse XML using C# and feel like I'm running in circles right now. I am calling a WCF web service which, based upon user input, conducts a search through a database against company names. It returns the results in an XML document with each entry formatted as it is below.
Given this XML structure, how would I go about obtaining the values for the
d:AccountId
andd:Name
nodes usingC#
?<entry> <id></id> <title type=\"text\"></title> <updated></updated> <author><name /></author> <link rel=\"edit\" title=\"Account\" href=\"AccountSet\" /> <category term=\"Microsoft.Crm.Sdk.Data.Services.Account\" scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\" /> <content type=\"application/xml\"> <m:properties> <d:neu_UniqueId></d:neu_UniqueId> <d:AccountId m:type=\"Edm.Guid\"></d:AccountId> <d:Name></d:Name> </m:properties></content> </entry>
Here is my first attempt. The program threw an exception at the
node3
variable.try { WebRequest myWebRequest = WebRequest.Create(URL); myWebRequest.PreAuthenticate = true; myWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials; //myWebRequest.Headers.Add("Access-Control-Allow-Origin", url); WebResponse myWebResponse = myWebRequest.GetResponse(); Stream myFileStreamResult = myWebResponse.GetResponseStream(); Encoding encoder = System.Text.Encoding.GetEncoding("utf-8"); StreamReader readStream = new StreamReader(myFileStreamResult, encoder); results = readStream.ReadToEnd(); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(results); XmlNodeList parentNode = xmlDoc.GetElementsByTagName("entry"); foreach (XmlNode childNode in parentNode) { string node = childNode.ToString(); string node2 = childNode.Value; string node3 = childNode.Attributes["title"].Value; string node7 = childNode.Attributes["m:properties"].Value; string node8 = childNode.Attributes["m:properties\\d:AccountId"].Value; string node9 = childNode.Attributes["m:properties\\d:Name"].Value; string node10 = childNode.Attributes["m:properties\\d:AccountId"].Value; } }
-
MarcinJuraszek about 11 years
m:
andd:
are namespaces. You should declare them first. Btw: Why don't you use LINQ to XML? -
Alexei Levenkov about 11 yearsAll "Attributes" you mentioned in code are actually "elements". It may be useful to scan MSDN for basic samples first (or w3c.org/xml if you really into reading XML)...
-
-
NealR about 11 yearsWould this path be used in the
.Attributes
method or.GetElementsByTagName
? -
evanmcdonnal about 11 years@NealR neither, you would use SelectNodes or SelectSingleNode in place of GetElementsBytTagName. I posted some sample code.
-
NealR about 11 yearsWhat would the
root
variable correspond to in your code? I tried using myxmlDoc
variable for this but got this error:Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function.
-
evanmcdonnal about 11 years@NealR sorry my example wasn't very clear. Check the example here which has code to load the doc ect - msdn.microsoft.com/en-us/library/h0hw012b.aspx