Reputation: 1481
I'm trying to load some values from an XML document returned by a Philips Hue Bridge. Here is an example of the XML I'm trying to parse (example taken from Philips' website):
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<URLBase>https://192.168.1.130:80/</URLBase>
<device>
<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>
<friendlyName>Philips hue (192.168.1.130)</friendlyName>
<manufacturer>Royal Philips Electronics</manufacturer><manufacturerURL>https://www.philips.com</manufacturerURL>
<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>
<modelName>Philips hue bridge 2012</modelName>
<modelNumber>929000226503</modelNumber>
<modelURL>https://www.meethue.com</modelURL>
<serialNumber>001788102201</serialNumber>
<UDN>uuid:2f402f80-da50-11e1-9b23-001788102201</UDN>
<presentationURL>index.html</presentationURL>
<iconList>
<icon>
<mimetype>image/png</mimetype>
<height>48</height>
<width>48</width>
<depth>24</depth>
<url>hue_logo_0.png</url>
</icon>
<icon>
<mimetype>image/png</mimetype>
<height>120</height>
<width>120</width>
<depth>24</depth>
<url>hue_logo_3.png</url>
</icon>
</iconList>
</device>
</root>
I've looked at several examples online and tried various paths, but the result is always null. I've put multiple examples in comments to show you some of the things I've tried.
var xml = webClient.DownloadString($"http://{bridge.internalipaddress.ToString()}/description.xml");
XmlDocument bridgeDetails = new XmlDocument();
bridgeDetails.LoadXml(xml);
XmlNode root = bridgeDetails.DocumentElement;
var friendlyName = bridgeDetails.SelectSingleNode("//device/friendlyName");
//var friendlyName = bridgeDetails.SelectSingleNode("/device/friendlyName");
//var friendlyName = bridgeDetails.SelectSingleNode("device/friendlyName");
//var friendlyName = bridgeDetails.SelectSingleNode("descendant::device/friendlyName");
//var friendlyName = root.SelectSingleNode("//device/friendlyName");
//var friendlyName = root.SelectSingleNode("/device/friendlyName");
//var friendlyName = root.SelectSingleNode("device/friendlyName");
//var friendlyName = root.SelectSingleNode("descendant::device/friendlyName");
//I've also tried adding .Value.ToString() at the end of some of these, but that just caused a null reference exception
EDIT:
I've worked out that I'm missing the namespace. But I'm not sure how as there is no URL to the namespace. E.g.
var nsmgr = new XmlNamespaceManager(bridgeDetails.NameTable);
nsmgr.AddNamespace("upnp", "urn:schemas-upnp-org:device-1-0");
XmlNode root = bridgeDetails.DocumentElement;
var friendlyName = bridgeDetails.SelectSingleNode("//upnp:device/friendlyName");
Any help would be appreciated.
Upvotes: 1
Views: 88
Reputation: 29042
Your solution after adding the namespace was close.
Now use the following XPath-1.0 expression, because all children or <root>
are in this namespace:
//upnp:device/upnp:friendlyName
In complete, this should look like
var friendlyName = bridgeDetails.SelectSingleNode("//upnp:device/upnp:friendlyName", nsmgr);
and return you the value
Philips hue (192.168.1.130)
Relating to your statement
But I'm not sure how as there is no URL to the namespace.
The namespace URI does not have to be a valid URL. It just has to be a unique string (in your "name"-space) and it doesn't have to point to a retrievable file. That's not neccessary.
Upvotes: 1