1

I'm trying to get a node from an XML string in C# using SelectSingleNode. The XML string comes from an external source.

string logonXML = @"<attrs xmlns=""http://www.sap.com/rws/bip\"">
                        <attr name=""userName"" type=""string""></attr>
                        <attr name=""password"" type=""string""></attr>
                        <attr name=""auth"" type=""string"" possibilities=""secEnterprise,secLDAP,secWinAD,secSAPR3"">secEnterprise</attr>
                    </attrs>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(logonXML);
XmlNode root = doc.DocumentElement;

XmlNode usernameXML = root.SelectSingleNode("//attr[@name='userName']");
Debug.WriteLine(usernameXML.OuterXml);

However usernameXML is null. I've tried using both the doc and root with a couple variations of XPath queries, but can't seem to find the node. What is wrong with this XPath? Or am I using the library wrong?

Paul
  • 3,725
  • 12
  • 50
  • 86
  • `("/attrs/attr[@name='username'])` ? – phadaphunk May 31 '13 at 20:40
  • `("/attrs/attr[1]")` ? – Reza Shirazian May 31 '13 at 20:41
  • I had tried this, but still comes back as `null`. – Paul May 31 '13 at 20:42
  • 1
    @RezaShirazian Works too. Only if the XML stays in that order though. – phadaphunk May 31 '13 at 20:42
  • 1
    The problem is that the element has a namespace (defaulted from the parent). There are lots of other examples of this on Stack Overflow - personally I'd use LINQ to XML instead (which has great namespace support) but there are alternatives for XPath too. – Jon Skeet May 31 '13 at 20:42
  • If you're failing to get what you want, try and approach it from the other way. See if you can get XmlDocument to give you the xpath for all its nodes. I would take a look at this: http://stackoverflow.com/questions/241238/how-to-get-xpath-from-an-xmlnode-instance-c-sharp – Reza Shirazian May 31 '13 at 20:51

1 Answers1

2

You need to take into account the XML namespace that's defined on your root node!

Try something like this:

string logonXML = @"<attrs xmlns=""http://www.sap.com/rws/bip"">
                        <attr name=""userName"" type=""string""></attr>
                        <attr name=""password"" type=""string""></attr>
                        <attr name=""auth"" type=""string"" possibilities=""secEnterprise,secLDAP,secWinAD,secSAPR3"">secEnterprise</attr>
                    </attrs>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(logonXML);

// define the XML namespace(s) that's in play here
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "http://www.sap.com/rws/bip");

// select including the XML namespace manager
XmlNode usernameXML = doc.SelectSingleNode("/ns:attrs/ns:attr[@name='userName']", nsmgr);

string test = usernameXML.InnerText;
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    Thanks, that was the issue. `doc.DocumentElement.NamespaceURI` will give me the namespace too, so I don't have to hardcode it. – Paul May 31 '13 at 20:54
  • 1
    @Paul: XML namespaces are there for a reason - you shouldn't try to avoid and strip them - get to know them, get used to them, respect them ! – marc_s May 31 '13 at 20:55