tags:

views:

69

answers:

2

I'm querying Sharepoint server-side and getting back results as Xml. I want to slim down the Xml into something more lightweight before sending it to jQuery through a WebMethod.

However my XPath query isn't working. I thought the following code would return all Document nodes, but it returns nothing. I've used XPath a little before, I thought //Document do the trick.

C# XPath query

XmlDocument xmlResults = new XmlDocument();
xmlResults.LoadXml(xml); // XML is a string containing the XML source shown below
XmlNodeList results = xmlResults.SelectNodes("//Document");

XML being queried

<ResponsePacket xmlns="urn:Microsoft.Search.Response">
      <Response domain="QDomain">
            <Range>
                  <StartAt>1</StartAt>
                  <Count>2</Count>
                  <TotalAvailable>2</TotalAvailable>
                  <Results>
                        <Document relevance="126" xmlns="urn:Microsoft.Search.Response.Document">
                              <Title>Example 1.doc</Title>
                              <Action>
                                    <LinkUrl size="32256" fileExt="doc">http://hqiis99/Mercury/Mercury documents/Example 1.doc</LinkUrl>
                              </Action>
                              <Description />
                              <Date>2010-08-19T14:44:56+01:00</Date>
                        </Document>
                        <Document relevance="31" xmlns="urn:Microsoft.Search.Response.Document">
                              <Title>Mercury documents</Title>
                              <Action>
                                    <LinkUrl size="0" fileExt="aspx">http://hqiis99/mercury/Mercury documents/Forms/AllItems.aspx</LinkUrl>
                              </Action>
                              <Description />
                              <Date>2010-08-19T14:49:39+01:00</Date>
                        </Document>
                  </Results>
            </Range>
            <Status>SUCCESS</Status>
      </Response>
</ResponsePacket>
+7  A: 

You're trying to select Document elements which don't have a namespace... whereas the default namespace is actually "urn:Microsoft.Search.Response" here.

I think you want something like this:

XmlDocument xmlResults = new XmlDocument();
xmlResults.LoadXml(xml);
XmlNamespaceManager manager = new XmlNamespaceManager(xmlResults.NameTable);
manager.AddNamespace("ns", "urn:Microsoft.Search.Response.Document");
XmlNodeList results = xmlResults.SelectNodes("//ns:Document", manager);

This finds two elements.


If you can use LINQ to XML instead, it makes it all somewhat easier:

XDocument results = XDocument.Parse(xml);
XNamespace ns = "urn:Microsoft.Search.Response.Document";
var documents = doc.Descendants(ns + "Document");

I love LINQ to XML's namespace handling :)

Jon Skeet
He has an additional namespace: `urn:Microsoft.Search.Response.Document`
Oded
I've no experience with Xml namespaces, what's the next step?
Peter Bridger
@Peter: Do you *definitely* want to use XPath here? LINQ to XML would make this easier, if you can use that.
Jon Skeet
@Jon-Skeet LINQ to XML is fine - my initials thoughts were that using XPath would be easier :) It's seems not! So feel free to update your answer with an LINQ to XML example and if it works I'll accept it.
Peter Bridger
@Peter: Have done - as well as leaving the XPath one.
Jon Skeet
@Oded: Thanks - I missed that before, and got confused when it didn't find anything :(
Jon Skeet
A: 

Alternatively, you could try the following and ignore the namespaces:

XmlDocument xmlResults = new XmlDocument();
xmlResults.LoadXml(xmlString);
XmlNodeList results = xmlResults.SelectNodes("//*[local-name()='Document']");
mnield
@mnield Interesting - thanks for the tip
Peter Bridger