0

I'm trying to get the inner text from a node after loading the XML file. I have tried this code with another file and it worked. But here I can't get the node values. Can anyone point out what am I doing wrong?

XML file - restaurant_reviews.xml

<?xml version="1.0"?>
<restaurants xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.algonquincollege.com/onlineservice/reviews">
  <restaurant>
    <name>Laughing Man</name>
    <logo>
      <name>Visit the Laughing Man</name>
      <imagefile>laughing-man.gif</imagefile>
      <width unit="px">50</width>
      <height unit="px">200</height>
    </logo>
  </restaurant>
  <restaurant>
    <name>Gong&#x2019;s Asian Cuisine</name>
    <logo>
      <name/>
      <imagefile>gong-asian-cuisine.gif</imagefile>
      <width unit="px">150</width>
      <height unit="px">250</height>
    </logo>
  </restaurant>
</restaurants>

C# Code

List<string> names = new List<string>();            
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath(@"~/App_Data/restaurant_reviews.xml"));
XmlNodeList nodes = xmlDoc.SelectNodes("/restaurants/restaurant");
foreach (XmlNode itemNode in nodes)
{
   XmlNode titleNode = itemNode.SelectSingleNode("name");
   if (titleNode != null)
   {
      names.Add(titleNode.InnerText);
   }

}
2
  • 1
    Your elements are within a namespace so you'll need to use an XmlNamespaceManager. Take a look at stackoverflow.com/questions/30279306/… Commented Apr 1, 2020 at 9:37
  • 1
    @Sean Thank you mate. This one was the main problem. Commented Apr 1, 2020 at 10:51

3 Answers 3

2

Whilst this question already has an accepted answer, I wanted to add this anyway, as removing namespaces and manipulating XML in this way doesn't feel right to me, it was added for a reason I suspect.

What I believe is the correct approach is too add an XML Namespace Manager to your XPath query.

var nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsMgr.AddNamespace("r", "http://www.algonquincollege.com/onlineservice/reviews");

Then in your SelectNodes and SelectSingleNodes, you add the namespace to the query and pass in the manager, like so.

XmlNodeList nodes = xmlDoc.SelectNodes("/r:restaurants/r:restaurant", nsMgr);

and

XmlNode titleNode = itemNode.SelectSingleNode("r:name", nsMgr);

But if you're happy with the other solution and can manipulate it in this way then go for it I guess.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you @Ryan Thomas I gave Presi's answer as accepted because it was resolving the issue. However yours and Sean's answer was the actual answer I was looking for.
I think this is a great solution. Didn't know the XmlNamespaceManager. Therefore I deleted it. But your answer is the much better solution!
1

If you remove this xmlns="http://www.algonquincollege.com/onlineservice/reviews" in your xml it works. I don't know why but the xmlDoc.SelectNodes("/restaurants/restaurant"); do not find any nodes with this xmlns namespace.

This is the code I worked with and it works:

string xml = @"<?xml version=""1.0""?>
    <restaurants xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
    <restaurant>
    <name>Laughing Man</name>
    <logo>
    <name>Visit the Laughing Man</name>
    <imagefile>laughing-man.gif</imagefile>
    <width unit=""px"">50</width>
    <height unit=""px"">200</height>
    </logo>
    </restaurant>
    <restaurant>
    <name>Gong&#x2019;s Asian Cuisine</name>
    <logo>
    <name/>
    <imagefile>gong-asian-cuisine.gif</imagefile>
    <width unit=""px"">150</width>
    <height unit=""px"">250</height>
    </logo>
    </restaurant>
    </restaurants>";
List<string> names = new List<string>();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
XmlNodeList nodes = xmlDoc.SelectNodes("/restaurants/restaurant");
foreach (XmlNode itemNode in nodes)
{
    XmlNode titleNode = itemNode.SelectSingleNode("name");
    if (titleNode != null)
    {
        names.Add(titleNode.InnerText);
    }
}

4 Comments

Thank you so much. I was banging my head for the last two days. That link was the problem.
@Abdullah-Al-Nahian Nice that I could help you!
Personally, I don't think removing XML Namespaces in this way is a good idea, so I have added an alternate answer.
@Presi my apologies for removing your answer as the accepted one. Because I want everyone to know the most accurate one. Which was provided by Sean and Ryan. Still your's one helped me big time. Thank you mate.
1

The problem was with namespace. Thanks to @Sean in the comment section I have resolved the issue. Thanks to @Presi also for pointing out the namespace attribute was the problem.

List<string> names = new List<string>();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(HttpContext.Current.Server.MapPath(@"~/App_Data/restaurant_reviews.xml"));
            var namespaceName = "ns";
            var namespacePrefix = string.Empty;
            XmlNamespaceManager nameSpaceManager = null;
            if (xmlDoc.LastChild.Attributes != null)
            {
                var xmlns = xmlDoc.LastChild.Attributes["xmlns"];
                if (xmlns != null)
                {
                    nameSpaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
                    nameSpaceManager.AddNamespace(namespaceName, xmlns.Value);
                    namespacePrefix = namespaceName + ":";
                }
            }

            XmlNodeList nodes = xmlDoc.SelectNodes(string.Format("/{0}restaurants/{0}restaurant", namespacePrefix), nameSpaceManager);
            foreach (XmlNode itemNode in nodes)
            {
                XmlNode titleNode = itemNode.SelectSingleNode(namespacePrefix + "name", nameSpaceManager);
                if (titleNode != null)
                {
                    names.Add(titleNode.InnerText);
                }

            }

1 Comment

Great answer! I know it wasn't the best solution to delete the namespace. Therefore your code is much better and is the right solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.