Thursday, October 4, 2012

How can we Specify Namespaces in XPath Queries without hard coding


When using XPath in .NET (via a navigator or SelectNodes/SelectSingleNode) on XML with namespaces you need to:
     Provide your own XmlNamespaceManager and explicitly prefix all elements in XPath expression, which are in namespace.

Please find the below sample:

XPathDocument xdoc = new XPathDocument(string.Format(@"{0}\SubmiOrderReq1.xml",Environment.CurrentDirectory));
XPathNavigator nav = xdoc.CreateNavigator();
XPathNodeIterator nodes = (XPathNodeIterator)nav.Evaluate("//namespace::*");
XmlNamespaceManager ns = new XmlNamespaceManager(new NameTable());

//Gets the name spaces from xml.
XmlDocument doc = new XmlDocument();
doc.Load(string.Format(@"{0}\[filename].xml", Environment.CurrentDirectory));

var namespaces = (from XmlNode n in doc.SelectNodes("//*|@*")
     where n.NamespaceURI != string.Empty
     select new
     {
          Prefix = n.Prefix,
          Namespace = n.NamespaceURI
     }).Distinct();

int count = 0;
foreach (var item in namespaces)
{
    ns.AddNamespace("ns" + count.ToString(), item.Namespace);
    count++;
}


Console.WriteLine("Payment type - CreditCard" + nav.Evaluate("count(//ns2:PaymentDetails[ns3:PaymentType = \"CreditCard\"])",ns));   //To get the CreditCard payment type PaymentDetails.
Console.WriteLine(nav.Evaluate("count(//ns2:ProductDetails)", ns));    //To get the ProductDetails count
Console.ReadLine();



The sample xml message structure looks like below
<RootNode>
     <Record>
          <PaymentDetails>
               <PaymentType> cash <PaymentType>
          <PaymentDetails>
          <PaymentDetails>
               <PaymentType> CreditCard <PaymentType>
          <PaymentDetails>

     </Record>
</RootNode>





No comments:

Post a Comment