Reputation: 65
I am trying to get the inner text of each domain node from an httpxml response.
I save the response to a string and load to XmlDocument
. But using the code below or variations of it I either get "CorpDomainMyDomain aaaa" or just "CorpDomain aaaa".
I have tried various iterations of domain and domains and cannot get the domains individually.
I would have thought that
XmlNodeList elemList = xmlDoc.SelectNodes("//DAV:domains", nsmgr);
would have created a list of each of the Domain elements but it doesn't seem that way.
The xml:
<?xml version="1.0" encoding="UTF-8" ?>
<multistatus xmlns="DAV:">
<response>
<propstat>
<prop>
<domains>
<domain logindefault="1" type="internal"><![CDATA[CorpDomain]]></domain>
<domain type="internal"><![CDATA[MyDomain]]></domain>
</domains>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
My code snippet
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("DAV", "DAV:");
XmlNodeList elemList = xmlDoc.SelectNodes("//DAV:domains", nsmgr);
foreach (XmlNode node in elemList)
{
strNode = node.SelectSingleNode("//DAV:domains", nsmgr).InnerText;
responseString = strNode+" aaaa ";
}
return responseString;
Upvotes: 1
Views: 1990
Reputation: 107357
(Even after you've fixed the responseString += strNode
issue that Ian picked up on, When you loop through the domain
elements under the domains
parent, you shouldn't again use //
- that will reset the context to the root of the document.
e.g. if your XmlDocument looks like:
<?xml version="1.0" encoding="UTF-8" ?>
<multistatus xmlns="DAV:">
<response>
<propstat>
<prop>
<domains>
<domain logindefault="1" type="internal">domains1-domain1</domain>
<domain type="internal">domains1-domain2</domain>
</domains>
</prop>
<prop>
<domains>
<domain logindefault="1" type="internal">domains2-domain1</domain>
<domain type="internal">domains2-domain2</domain>
</domains>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
your code would in fact scrape the combined text nodes of all child nodes of just the first domains
element, i.e. something like (where aaaa
is your delimiter):
domains1-domain1 aaaa domains1-domain2 aaaa
Instead, you should just provide the relative pathing from parent to child, i.e. just domain
in your case. Assuming that there are N domains
parent elements each with M domain
child elements, if you stop at the parent nodes, you will need a second level of iteration through the child nodes:
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("DAV", "DAV:");
XmlNodeList elemList = xmlDoc.SelectNodes("//DAV:domains", nsmgr);
foreach (var domains in elemList)
{
foreach (var domain in domains.SelectNodes("DAV:domain", nsmgr))
{
strNode = domain.InnerText;
responseString = strNode+" aaaa ";
}
}
return responseString;
But if you don't need to retain a reference to the parent for other purposes, you could also do this in one step by flattening out the child nodes directly. For large xml documents with many nodes, it would also be a good idea to avoid the string concatenation problem, e.g. with a StringBuilder
:
var sb = new StringBuilder();
foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:domains/DAV:domain", nsmgr))
{
var strNode = node.InnerText;
sb.Append(strNode); // do the same for delimiter
}
// use sb.ToString() here.
Upvotes: 1