4

I am trying to select values from elements using the XPathNodeIterator. But I am not able to get the expected value from my XML file.

My XML file

<?xml version="1.0" encoding="utf-8"?>
<ns0:Entity xmlns:ns0="http://schemas.mycompany.com/1.0">
    <ns0:Data>
        <Address_Id xmlns:ns0="http://schemas.mycompany.com/1.0">7</Address_Id>
        <Customer_Id xmlns:ns0="http://schemas.mycompany.com/1.0">67</Customer_Id>
        <CustomerName xmlns:ns0="http://schemas.mycompany.com/1.0">My Customer 1</CustomerName>
    </ns0:Data>
</ns0:Entity>

My methods to get the values
I have created two methods which both doesn't return the values which I would like to have.

private static string GetValue_Attempt1(XPathDocument xPathDocument, string xpathExpression)
{
    var xpathNavigator = xPathDocument.CreateNavigator();
    var xpathNodeIterator = xpathNavigator.Select(xpathExpression);
    xpathNodeIterator.MoveNext();
    return xpathNodeIterator.Current.Value;
}

private static string GetValue_Attempt2(XPathDocument xPathDocument, string xpathExpression)
{
    var xpathNavigator = xPathDocument.CreateNavigator();
    var xpathNodeIterator = xpathNavigator.Select(xpathExpression);
    xpathNodeIterator.MoveNext();
    var nodesNavigator = xpathNodeIterator.Current;
    var nodesText = nodesNavigator.SelectDescendants(XPathNodeType.Text, false);
    nodesText.MoveNext();
    return nodesText.Current.Value;
}

My XPath

  • Get Address_Id
    • XPath: //Data/Address_Id/text()
    • Attempt1 returns: 767My Customer 1. Why are all values concatenated ???
    • Attempt2 returns: 7. Looks OK
  • Get Customer_Id
    • XPath: //Data/Customer_Id/text()
    • Attempt1 returns: 767My Customer 1. Why are all values concatenated ???
    • Attempt2 returns: 7. Why do I get the Address_Id??

Questions
Probably I am using an incorrect XPath. But also I don't understand the results. In order to understand whats going on. I would like to know:

  1. Is there a better way (method) to get the value of the elements?
  2. What is the XPath string which I need to use?
  3. Why does method GetValue_Attempt1 return a concatinated string?
  4. Why does method GetValue_Attempt2 return the value of only the first element?
hwcverwe
  • 5,287
  • 7
  • 35
  • 63

1 Answers1

4

Your XPath returns no matches as you're not taking the namespaces into account.

Your 'Attempt 1' calls MoveNext() once, so Value returns all the concatenated text in Data, and in 'Attempt 2' you call MoveNext() twice which positions you inside the Address_Id element.

In addition, Select, even it the XPath was valid, doesn't actually move the cursor.

If you wanted to get the value, you'd do something like this - note I'm including the namespace in the XPath and using the result of SelectSingleNode:

var nsm = new XmlNamespaceManager(new NameTable());
nsm.AddNamespace("ns0", "http://schemas.mycompany.com/1.0");

var value = navigator.SelectSingleNode("//ns0:Data/Address_Id", nsm).Value;

However, do you have any reason to be using XPath and XPathDocument here? Using the much more expressive and (more) statically typed LINQ to XML would be far preferable, I'd think:

XNamespace ns = "http://schemas.mycompany.com/1.0";

var doc = XDocument.Parse(xml);

var addressId = (int)doc.Descendants(ns + "Data")
    .Elements("Address_Id")
    .Single();

var customerId = (int)doc.Descendants(ns + "Data")
    .Elements("Customer_Id")
    .Single();
Charles Mager
  • 25,735
  • 2
  • 35
  • 45