Web Service Results – XPath is your friend!

Yesterday Eric Shupps posted about retrieving error messages from SharePoint web services. I noticed he uses XPath to retrieve the error codes, but then falls back on object manipulation to filter for real errors and to retrieve the error message:

XmlNode ndRoot = xmlResult.SelectSingleNode("sp:Results", nsMgr);
// Find the ErrorCode node, which exists for all operations regardless of status.
XmlNodeList nlResults = ndRoot.SelectNodes("//sp:Result/sp:ErrorCode", nsMgr);
// Loop through the node collection and find each ErrorCode entry
foreach (XmlNode ndResult in nlResults) {
  // Check the value of the node to determine its status
  if (ndResult.InnerText != "0x00000000") {
    XmlNode ndError = ndResult.NextSibling;
    string sError = ndError.InnerText;
    …

Just like we wouldn’t omit a SQL WHERE clause in favor of filtering a DataSet with string comparison, we should probably let XPath do as much for us as possible. In this case a few tweaks reduce the logic to a single selection, also offering a quick exit if there are no errors found:

// Find the ErrorText for Result nodes with non-zero ErrorCode.
string xpath = "/sp:Results/sp:Result[sp:ErrorCode != '0x00000000']/sp:ErrorText";
XmlNodeList nlErrors = xmlResult.SelectNodes(xpath, nsMgr);
if (nlErrors.Count == 0) {
  // No errors - return "Success", false, null, whatever
}
foreach (XmlNode ndError in nlErrors) {
  string sErrorText = ndError.InnerText;
  …

As Eric mentioned, there are a few ways to handle the error(s) returned. I thought it might be useful to pair the ErrorText with the ID of the method that generated it:

// Key = Method ID; Value = Error Text
static Dictionary<string, string> GetErrors(XmlDocument xmlResult) {
  XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlResult.NameTable);
  XmlElement ndRoot = xmlResult.DocumentElement;
  nsMgr.AddNamespace("sp", ndRoot.NamespaceURI);

  // Find the ErrorText for Result nodes with non-zero ErrorCode.
  string xpath = "/sp:Results/sp:Result[sp:ErrorCode != '0x00000000']/sp:ErrorText";
  XmlNodeList nlErrors = ndRoot.SelectNodes(xpath, nsMgr);

  if (nlErrors.Count == 0) {
    return null;
  }

  Dictionary<string, string> errorDict = new Dictionary<string, string>(nlErrors.Count);
  foreach (XmlNode ndError in nlErrors) {
    XmlNode ndResultId = ndError.ParentNode.Attributes["ID"];
    if (ndResultId != null) {
      errorDict.Add(ndResultId.Value, ndError.InnerText);
    }
  }
  return errorDict;
}

I figure a single XPath selection plus a reference to ParentNode would be more efficient than selecting the Result node for the ID and then finding its ErrorText child from there. And of course if there are better ways to do this, please share!

About these ads

One Response to “Web Service Results – XPath is your friend!”

  1. Michael Greth MVP SharePoint Blog : SharePoint Kaffeetasse #85 Says:

    [...] Web Service Results – XPath is your friend! [...]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: