Reputation: 11680
I'm trying to pull some values from some customer-supplied XML documents, using XmlDocument.SelectSingleNode().
SelectSingleNode() takes an XPATH string, and very simple searches are failing. E.g. with this:
<?xml version="1.0"?>
<xmlTicket>
<TicketDataSet xmlns="http://tempuri.org/Ticket.xsd">
<Ticket>
<TicketNumber>0123-456-789</TicketNumber>
...
</Ticket>
</TicketDataSet>
</xmlTicket>
XmlDocument.SelectSingleNode("//TicketNumber") returns null.
The problem is clearly the namespace. If I remove the xmlns= from the doc, the XPATHs work fine. If I use namespace neutral XPATH queries, they also work fine:
doc.SelectSingleNode("//*[local-name()='TicketNumber']");
But I can't do the former and I'd rather not do the latter.
I've found examples of how to configure a namespace manager, and tried to work out how to make this work for a default namespace.
This didn't work:
var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("", "http://tempuri.org/Ticket.xsd");
var ticketNumberNode = doc.SelectSingleNode("//TicketNumber", nsm);
And this didn't work:
var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("default", "http://tempuri.org/Ticket.xsd");
var ticketNumberNode = doc.SelectSingleNode("//default:TicketNumber", nsm);
Any ideas?
===
Note: I updated the XML to show more of the structure. The problem seems to be related to having default namespaces applied to parts of the document, rather than to its entirety.
Upvotes: 0
Views: 2982
Reputation: 1
The solution is strange but you should specify namespace with prefix in SelectionNamespaces property and specify this prefix in XPath queries. It doesn't matter if this namespace is default namespace with no prefix: you should use one. On the other side, you should add nodes to XML without prefix.
In your example the code should looks like this:
doc.setProperty("SelectionNamespaces", "xmlns:abc='http://tempuri.org/Ticket.xsd'");
doc.selectSingleNode("//abc:TicketNumber");
Upvotes: 0
Reputation: 34421
Try xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
string ticketNumber = (string)doc.Descendants().Where(x => x.Name.LocalName == "TicketNumber").FirstOrDefault();
}
}
}
Upvotes: 0