coopermj
coopermj

Reputation: 631

GDataXML, namespaces, and xpath

I'm having trouble parsing XML using xpath and GDataXML -- using an xpath tester, my string seems that it should work, but I think adding in the namespace is interfering with it working.

XML:

<?xml version="1.0" encoding="utf-8"?>

<Autodiscover xmlns='http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006'>
          <Response xmlns='http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a'>
        <Account>
        <Protocol>
                <Type>EXPR</Type>
                <EwsUrl>https://server.my.dom/EWS/Exchange.asmx</EwsUrl>
        </Protocol>
        </Account>
      </Response>
</Autodiscover>

My attempt to parse it is as follows:

NSDictionary *namespaceMappings = [NSDictionary dictionaryWithObjectsAndKeys:@"http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a", @"response", nil];

    NSArray *idList = [doc nodesForXPath:@"//response:Protocol[Type='EXPR']/EwsUrl" namespaces:namespaceMappings error:nil];

I've also tried leaving out the namespace with the following:

NSArray *idList = [doc nodesForXPath:@"//Protocol[Type='EXPR']/EwsUrl" error:nil];

In both scenarios, idList has 0 members. I feel as if I'm just tossing things against the wall now to see if anything sticks. Can someone show me the way?

Thanks!

Upvotes: 1

Views: 1511

Answers (2)

Mick Byrne
Mick Byrne

Reputation: 14484

Martin's answer is correct, but I thought I'd just spell out why for those that missed it on first reading (like me).

When you set the namespace mappings, give the namespace a key, then prefix your selectors in your XPath expressions with that key followed by a colon (:). This solution uses CXMLDocuments and CXMLElements from the neat TouchXML library.

To start with a simple example, say your XML was:

<books xmlns="http://what.com/ever">
  <book>
    <title>Life of Pi</title>
  </book>
  <book>
    <title>Crime and Punishment</book>
  </book
</books>

You would select all the books with:

// So, assuming you've already got the data for the XML document
CXMLDocument* xmldoc = [[CXMLDocument alloc] initWithData:xmlDocData options:0 error:nil];
NSDictionary *namespaceMappings = [NSDictionary dictionaryWithObjectsAndKeys:@"http://what.com/ever", @"nskey", nil];
NSError *error = nil;
NSArray *bookElements = [xmldoc nodesForXPath:@"/nskey:books/nskey:book" namespaceMappings:mappings error:&error];

Note that you need to prefix every element, not just the one where the namespace is declared.

Upvotes: 3

Martin Honnen
Martin Honnen

Reputation: 167571

As for the XPath, you need //response:Protocol[response:Type='EXPR']/response:EwsUrl. I can't help with the objective-c stuff.

Upvotes: 2

Related Questions