Index: bibdesk/BDSKGoogleScholarParser.m
===================================================================
--- bibdesk/BDSKGoogleScholarParser.m	(revision 13589)
+++ bibdesk/BDSKGoogleScholarParser.m	(working copy)
@@ -46,6 +46,7 @@
 + (BOOL)canParseDocument:(DOMDocument *)domDocument xmlDocument:(NSXMLDocument *)xmlDocument fromURL:(NSURL *)url{
     
     // !!! other countries end up with e.g. scholar.google.be; checking for scholar.google.com may fail in those cases
+    // also some sites access google scholar via an ezproxy, so the suffix could be quite complex
     if (! [[url host] hasPrefix:@"scholar.google."]){
         return NO;
     }
@@ -68,34 +69,84 @@
 
     NSMutableArray *items = [NSMutableArray arrayWithCapacity:0];
     
+    NSString *googSearchResultNodePath = @"//p[@class='g']";
     
-    NSString *BibTexLinkNodePath = @"//a[contains(text(),'BibTeX')]";
+    NSString *BibTexLinkNodePath = @".//a[contains(text(),'BibTeX')]";
+	
+    NSString *targetUrlNodePath = @".//span[@class='w']/a";
     
-    NSError *error = nil;    
-
-    NSArray *BibTeXLinkNodes = [[xmlDocument rootElement] nodesForXPath:BibTexLinkNodePath
-                                                    error:&error];
-        
+    NSError *error = nil;
+    
+    // fetch the google search results
+    NSArray *googSearchResults = [[xmlDocument rootElement] nodesForXPath:googSearchResultNodePath
+                                                                    error:&error];
+    
     // bail out with an XML error if the Xpath query fails
-    if (nil == BibTeXLinkNodes) {
+    if (nil == googSearchResults) {
         if (outError) *outError = error;
         return nil;
-    }
+    }    
     
-    unsigned int i, iMax = [BibTeXLinkNodes count];
+    unsigned int i, iMax = [googSearchResults count];
     
     // check the number of nodes first
     if (0 == iMax) {
-        error = [NSError mutableLocalErrorWithCode:kBDSKUnknownError localizedDescription:NSLocalizedString(@"No BibTeX links found", @"Google scholar error")];
+        error = [NSError mutableLocalErrorWithCode:kBDSKUnknownError localizedDescription:NSLocalizedString(@"No search results found", @"Google scholar error")];
         [error setValue:NSLocalizedString(@"Unable to parse this page.  Please report this to BibDesk's developers and provide the URL.", @"Google scholar error") forKey:NSLocalizedRecoverySuggestionErrorKey];
         if (outError) *outError = error;
         return nil;
     }
-    
+        
     for(i=0; i < iMax; i++){
         
-        NSXMLNode *btlinknode = [BibTeXLinkNodes objectAtIndex:i];
+        NSXMLNode *googSearchResult = [googSearchResults objectAtIndex:i];
         
+        NSString *targetUrlHrefValue = nil;
+        
+        // fetch the bibtex link
+        
+        NSArray *BibTeXLinkNodes = [googSearchResult nodesForXPath:BibTexLinkNodePath
+                                                             error:&error];
+        
+        if (nil == BibTeXLinkNodes) {
+
+            // TODO: set the NSError properly here
+            NSLog(@"Google Scholar Error: unable to parse bibtex url from search result %u due to xpath error", i);
+            continue;
+
+        } else if (1 != [BibTeXLinkNodes count]) {
+
+            // TODO: set the NSError properly here
+            NSLog(@"Google Scholar Error: unable to parse bibtex url from search result %u, found %u bibtex urls (expected 1)", i, [BibTeXLinkNodes count]);
+            continue;
+
+        }
+        
+        // fetch the actual item url
+        NSArray *targetUrlNodes = [googSearchResult nodesForXPath:targetUrlNodePath
+                                                            error:&error];
+        
+        // skip if the target xpath fails, but continue with the bibtex import - some result
+        // types have no url (eg. Book or Citation entries)
+        if (nil == targetUrlNodes) {
+            
+            // TODO: set the NSError properly here
+            NSLog(@"Google Scholar Error: unable to parse target url from search result %u due to xpath error", i);
+
+        } else if (1 != [targetUrlNodes count]) {
+            
+            // TODO: set the NSError properly here
+            NSLog(@"Google Scholar Error: unable to parse target url from search result %u, found %u target urls (expected 1)", i, [targetUrlNodes count]);
+
+        } else {
+            
+            // successfully found the result target url
+            targetUrlHrefValue = [[targetUrlNodes objectAtIndex:0] stringValueOfAttribute:@"href"];
+        }
+        
+        
+        NSXMLNode *btlinknode = [BibTeXLinkNodes objectAtIndex:0];
+        
         NSString *hrefValue = [btlinknode stringValueOfAttribute:@"href"];
         
         
@@ -134,13 +185,9 @@
             bibtexItems = [BDSKBibTeXParser itemsFromString:bibTeXString document:nil isPartialData:&isPartialData error:&error];
         
         if ([bibtexItems count] && NO == isPartialData) {
-        BibItem *bibtexItem = [bibtexItems objectAtIndex:0]; 
+            BibItem *bibtexItem = [bibtexItems objectAtIndex:0]; 
         
-        // TODO: get a useful link for the URL field. 
-        // each item's title looks like <span class="w"><a href="link">title</a></span>
-        // but it'll take some xpath hacking to make sure we match title to bibtex link correctly.
-        
-        [items addObject:bibtexItem];
+            [items addObject:bibtexItem];
 			
 			NSString *bracedTitle = [bibtexItem valueOfField:BDSKTitleString inherit:NO];
 			
@@ -152,7 +199,13 @@
 				if ([mutableTitle isStringTeXQuotingBalancedWithBraces:YES connected:NO]) 
 					[bibtexItem setField:BDSKTitleString toValue:mutableTitle];
 				[mutableTitle release];
-			}				
+			}
+            
+            if (targetUrlHrefValue) {
+                
+                // target url was found successfully
+                [bibtexItem setField:BDSKUrlString toValue:targetUrlHrefValue];
+            }
         }
         else {
             // display a fake item in the table so the user knows one of the items failed to parse, but still gets the rest of the data
