Reputation: 862
I have been looking for ages to find a way to select nodes from an XmlNode
(NOT AN XmlDocument
) which has multiple namespaces.
Almost every post that I have searched has advised me to use an XmlNamespaceManager
, however, XmlNamespaceManager
needs an XmlNameTable
which does not exists for an XmlNode
.
I tried doing this with an XmlDocument
and it worked since XmlDocument
has a property XmlDocument.NameTable
but it does not exists for XmlNode.
I tried creating a NameTable manually but it does not work as the same piece of code works when I use an XmlDocument
. I guess I need to populate that NameTable with something or somehow bind it to the XmlNode
to make this work. Please suggest.
Upvotes: 3
Views: 2648
Reputation: 746
For some reason the XmlNamespaceManager doesn't automatically load the defined namespaces in the document (This seems like a simple expectation). For some reason the namespace declarations are treated as attributes. I was able to automate adding the namespaces using the following code.
private static XmlNamespaceManager AddNamespaces(XmlDocument xmlDoc)
{
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
AddNamespaces(xmlDoc.ChildNodes, nsmgr);
return nsmgr;
}
private static void AddNamespaces(XmlNodeList nodes, XmlNamespaceManager nsmgr) {
if (nodes == null)
throw new ArgumentException("XmlNodeList is null");
if (nsmgr == null)
throw new ArgumentException("XmlNamespaceManager is null");
foreach (XmlNode node in nodes)
{
if (node.NodeType == XmlNodeType.Element)
{
foreach (XmlAttribute attr in node.Attributes)
{
if (attr.Name.StartsWith("xmlns:"))
{
String ns = attr.Name.Replace("xmlns:", "");
nsmgr.AddNamespace(ns, attr.Value);
}
}
if (node.HasChildNodes)
{
nsmgr.PushScope();
AddNamespaces(node.ChildNodes, nsmgr);
nsmgr.PopScope();
}
}
}
}
Sample call example:
XmlDocument ResponseXmlDoc = new System.Xml.XmlDocument();
...<Load your XML Document>...
XmlNamespaceManager nsmgr = AddNamespaces(ResponseXmlDoc);
And use the returned NamespaceManager
XmlNodeList list = ResponseXmlDoc.SelectNodes("//d:response", nsmgr);
Upvotes: 0
Reputation: 1142
Can you use
XPathNavigator nav = XmlNode.CreateNavigator();
XmlNamespaceManager man = new XmlNamespaceManager(nav.NameTable);
Including the rest in case it'll be helpful:
man.AddNamespace("app", "http://www.w3.org/2007/app"); //Gotta add each namespace
XPathNodeIterator nodeIter = nav.Select(xPathSearchString, man);
while (nodeIter.MoveNext())
{
var value = nodeIter.Current.Value;
}
http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.createnavigator.aspx
Upvotes: 4