Revision: 22515
          http://sourceforge.net/p/bibdesk/svn/22515
Author:   hofman
Date:     2018-08-23 13:46:51 +0000 (Thu, 23 Aug 2018)
Log Message:
-----------
Methods to get a single DOMNode from an XPath, can be more efficient

Modified Paths:
--------------
    trunk/bibdesk/BDSKArxivParser.m
    trunk/bibdesk/BDSKAsynchronousWebParser.m
    trunk/bibdesk/BDSKCOinSParser.m
    trunk/bibdesk/BDSKDOIWebParser.m
    trunk/bibdesk/BDSKHCiteParser.m
    trunk/bibdesk/BDSKIACRParser.m
    trunk/bibdesk/BDSKIEEEXploreParser.m
    trunk/bibdesk/BDSKInspireParser.m
    trunk/bibdesk/BDSKNumdamParser.m
    trunk/bibdesk/BDSKProjectEuclidParser.m
    trunk/bibdesk/BDSKSpringerParser.m
    trunk/bibdesk/DOMNode_BDSKExtensions.h
    trunk/bibdesk/DOMNode_BDSKExtensions.m

Modified: trunk/bibdesk/BDSKArxivParser.m
===================================================================
--- trunk/bibdesk/BDSKArxivParser.m     2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKArxivParser.m     2018-08-23 13:46:51 UTC (rev 22515)
@@ -63,9 +63,9 @@
     else
         return NO;
     
-    NSInteger nodecount = [[[domDocument documentElement] 
nodesForXPath:containsArxivLinkNode] count];
+    DOMNode *node = [[domDocument documentElement] 
singleNodeForXPath:containsArxivLinkNode];
     
-    return nodecount > 0;
+    return node != nil;
 }
 
 - (NSArray *)itemsReturningError:(NSError **)outError {
@@ -161,26 +161,25 @@
     for (DOMNode *arxivSearchResult in arxivSearchResults) {
         
         // fetch the arxiv links
-        NSArray *nodes = [arxivSearchResult 
nodesForXPathExpression:arxivLinkNodePath];
+        DOMNode *arxivNode = [arxivSearchResult 
singleNodeForXPathExpression:arxivLinkNodePath];
         
-        if (1 != [nodes count]) {
+        if (arxivNode == nil) {
             // If arXiv ever start providing multiple alternative bibtex links 
for a
             // single item we will need to deal with that
-            NSLog(@"ArXiv Error: unable to parse bibtex url from search 
result, found %lu bibtex urls (expected 1)", (unsigned long)[nodes count]);
+            NSLog(@"ArXiv Error: unable to parse bibtex url from search 
result");
             continue;
         }
         
-        DOMNode *arxivNode = [nodes objectAtIndex:0];
-        DOMNode *node;
-        
         NSMutableDictionary *pubFields = [NSMutableDictionary dictionary];
         NSMutableArray *pubFiles = [NSMutableArray array];
         NSString *string = nil;
         
+        NSArray *nodes;
+        DOMNode *node;
+        
         // search for arXiv ID
-        nodes = [arxivNode nodesForXPathExpression:arxivIDNodePath];
-        if (1 == [nodes count]) {
-            node = [nodes firstObject];
+        node = [arxivNode singleNodeForXPathExpression:arxivIDNodePath];
+        if (node) {
             if ((string = [node stringValue])) {
                 if ([string hasCaseInsensitivePrefix:@"arXiv:"])
                     string = [string substringFromIndex:6];
@@ -200,10 +199,10 @@
             arxivNode = arxivSearchResult;
         
         // search for PDF
-        nodes = [arxivNode nodesForXPathExpression:pdfURLNodePath];
-        if (1 == [nodes count]) {
+        node = [arxivNode singleNodeForXPathExpression:pdfURLNodePath];
+        if (node) {
             // successfully found the result PDF url
-            if ((string = [[nodes firstObject] getAttribute:@"href"])) {
+            if ((string = [(DOMElement *)node getAttribute:@"href"])) {
                 // fix relative urls
                 if (NO == [string containsString:@"://"])
                     string = [[NSURL URLWithString:string relativeToURL:url] 
absoluteString];
@@ -214,24 +213,24 @@
         }
         
         // search for DOI
-        nodes = [arxivNode nodesForXPathExpression:doiNodePath];
-        if (1 == [nodes count]) {
+        node = [arxivNode singleNodeForXPathExpression:doiNodePath];
+        if (node) {
             // successfully found the result PDF url
-            if ((string = [[nodes firstObject] stringValue])) {
+            if ((string = [node stringValue])) {
                 [pubFields setValue:string forKey:BDSKDoiString];
             }
         }
         
         if (arxivNodePath) {
-            arxivNode = [[arxivSearchResult 
nodesForXPathExpression:arxivNodePath] firstObject];
+            arxivNode = [arxivSearchResult 
singleNodeForXPathExpression:arxivNodePath];
         } else {
             arxivNode = arxivSearchResult;
         }
         
         // search for title
-        nodes = [arxivNode nodesForXPathExpression:titleNodePath];
-        if (1 == [nodes count]) {
-            if ((string = [[nodes firstObject] stringValue])) {
+        node = [arxivNode singleNodeForXPathExpression:titleNodePath];
+        if (node) {
+            if ((string = [node stringValue])) {
                 [pubFields setValue:string forKey:BDSKTitleString];
             }
         }
@@ -245,9 +244,9 @@
         }
         
         // search for journal ref
-        nodes = [arxivNode nodesForXPathExpression:journalNodePath];
-        if (1 == [nodes count]) {
-            if ((string = [[nodes firstObject] stringValue])) {
+        node = [arxivNode singleNodeForXPathExpression:journalNodePath];
+        if (node) {
+            if ((string = [node stringValue])) {
                 // try to get full journal ref components, as "Journal Volume 
(Year) Pages"
                 AGRegexMatch *match = [journalRegex1 findInString:string];
                 if ([match groupAtIndex:0]) {
@@ -275,9 +274,9 @@
         }
         
         // search for abstract
-        nodes = [arxivNode nodesForXPathExpression:abstractNodePath];
-        if (1 == [nodes count]) {
-            if ((string = [[nodes firstObject] stringValuePreservingBreaks])) {
+        node = [arxivNode singleNodeForXPathExpression:abstractNodePath];
+        if (node) {
+            if ((string = [node stringValuePreservingBreaks])) {
                 if (isAbstract && [string hasPrefix:@"Abstract: "])
                     string = [string substringFromIndex:10];
                 if (isSearch && [string hasSuffix:@"\u25B3 Less"])

Modified: trunk/bibdesk/BDSKAsynchronousWebParser.m
===================================================================
--- trunk/bibdesk/BDSKAsynchronousWebParser.m   2018-08-23 13:10:05 UTC (rev 
22514)
+++ trunk/bibdesk/BDSKAsynchronousWebParser.m   2018-08-23 13:46:51 UTC (rev 
22515)
@@ -68,12 +68,12 @@
     if ([url hasDomain:host] == NO)
         return NO;
     
-    NSArray *nodes = [[domDocument documentElement] nodesForXPath:[self 
citationNodeXPath]];
+    DOMNode *node = [[domDocument documentElement] singleNodeForXPath:[self 
citationNodeXPath]];
     
-    if ([nodes count] == 0)
+    if (node == nil)
         return NO;
     
-    return nil != [self citationURLStringFromNode:[nodes firstObject]];
+    return nil != [self citationURLStringFromNode:node];
 }
 
 - (NSArray *)itemsReturningError:(NSError **)outError {

Modified: trunk/bibdesk/BDSKCOinSParser.m
===================================================================
--- trunk/bibdesk/BDSKCOinSParser.m     2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKCOinSParser.m     2018-08-23 13:46:51 UTC (rev 22515)
@@ -69,9 +69,9 @@
 // Claim that the can parse the document if its markup contains the string 
Z3988.
 + (BOOL)canParseDocument:(DOMDocument *)domDocument fromURL:(NSURL *)url{
        
-    NSArray *nodes = [[domDocument documentElement] 
nodesForXPath:hasCOinSNodesXPath];
+    DOMNode *node = [[domDocument documentElement] 
singleNodeForXPath:hasCOinSNodesXPath];
     
-    return [nodes count] > 0;
+    return node != nil;
 }
 
 // Convert publication type name from COinS to BibTeX names.

Modified: trunk/bibdesk/BDSKDOIWebParser.m
===================================================================
--- trunk/bibdesk/BDSKDOIWebParser.m    2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKDOIWebParser.m    2018-08-23 13:46:51 UTC (rev 22515)
@@ -49,6 +49,7 @@
     DOMNode *rootElement = [domDocument documentElement];
     NSString *doiXPath;
     NSArray *nodes;
+    DOMNode *node;
     
     doiXPath = 
@"./head/meta[starts-with(translate(@content,'DOI','doi'),'doi:') or 
starts-with(@content,'10.')]";
     nodes = [rootElement nodesForXPath:doiXPath];
@@ -55,7 +56,7 @@
     
     if ([nodes count] > 0) {
         NSSet *names = [NSSet setWithObjects:@"citation_doi", @"doi", 
@"prism.doi", @"dc.identifier", nil];
-        for (DOMNode *node in nodes) {
+        for (node in nodes) {
             if ([names containsObject:[[node nodeName] lowercaseString]])
                 return YES;
         }
@@ -62,9 +63,9 @@
     }
     
     doiXPath = @"./body//a[starts-with(@href,'https://doi.org/') or 
starts-with(@href,'http://dx.doi.org/')]";
-    nodes = [rootElement nodesForXPath:doiXPath];
+    node = [rootElement singleNodeForXPath:doiXPath];
     
-    if ([nodes count] > 0)
+    if (node != nil)
         return YES;
     
     NSString *text = [[domDocument body] textContent];

Modified: trunk/bibdesk/BDSKHCiteParser.m
===================================================================
--- trunk/bibdesk/BDSKHCiteParser.m     2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKHCiteParser.m     2018-08-23 13:46:51 UTC (rev 22515)
@@ -56,9 +56,9 @@
 + (BOOL)canParseDocument:(DOMDocument *)domDocument fromURL:(NSURL *)url{
     
     NSString *hciteXpath = @".//*[contains(concat(' ',normalize-space(@class), 
' '),' hcite ') and not(contains(concat(' ', normalize-space(@class), ' '),' 
container '))]";
-    NSArray *mainNodes = [[domDocument documentElement] 
nodesForXPath:hciteXpath];
+    DOMNode *mainNode = [[domDocument documentElement] 
singleNodeForXPath:hciteXpath];
     
-    return [mainNodes count] > 0;
+    return mainNode != nil;
 }
 
 - (NSArray *)itemsReturningError:(NSError **)outError {
@@ -162,10 +162,10 @@
     
     // find date published
     
-    NSArray *datePublishedNodes = [citationNode 
nodesForXPathExpression:[xpaths objectForKey:@"date-published"]];
+    // Only use the first such node.
+    DOMNode *datePublishedNode = [citationNode 
singleNodeForXPathExpression:[xpaths objectForKey:@"date-published"]];
     
-    if([datePublishedNodes count] > 0) {
-        DOMNode *datePublishedNode = [datePublishedNodes objectAtIndex:0]; // 
Only use the first such node.
+    if(datePublishedNode) {
         NSDate *datePublished = [self dateFromNode:datePublishedNode];
         NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
         [formatter setFormatterBehavior:NSDateFormatterBehavior10_4];
@@ -178,32 +178,31 @@
     
     // find issue
     
-    NSArray *issueNodes = [citationNode nodesForXPathExpression:[xpaths 
objectForKey:@"issue"]];
+    // Only use the first such node.
+    DOMNode *issueNode = [citationNode singleNodeForXPathExpression:[xpaths 
objectForKey:@"issue"]];
     
-    if([issueNodes count] > 0) {
-        // Only use the first such node.
-        [rd setObject:[[issueNodes objectAtIndex:0] stringValue] 
forKey:@"Issue"];
+    if(issueNode) {
+        [rd setObject:[issueNode stringValue] forKey:@"Issue"];
     }
     
     // find pages
     
-    NSArray *pagesNodes = [citationNode nodesForXPathExpression:[xpaths 
objectForKey:@"pages"]];
+    // Only use the first such node.
+    DOMNode *pagesNode = [citationNode singleNodeForXPathExpression:[xpaths 
objectForKey:@"pages"]];
     
-    if([pagesNodes count] > 0) {
-        // Only use the first such node.
-        [rd setObject:[[pagesNodes objectAtIndex:0] stringValue] 
forKey:BDSKPagesString];
+    if(pagesNode) {
+        [rd setObject:[pagesNode stringValue] forKey:BDSKPagesString];
     }
     
     // find URI
     
-    NSArray *URINodes = [citationNode nodesForXPathExpression:[xpaths 
objectForKey:@"uri"]];
+    DOMNode *URINode = [citationNode singleNodeForXPathExpression:[xpaths 
objectForKey:@"uri"]];
     
-    if([URINodes count] > 0) {
-        DOMElement *URINode = [URINodes objectAtIndex:0]; // Only use the 
first such node.
+    if(URINode) {
         NSString *URIString = nil;
         
         if([[URINode nodeName] isCaseInsensitiveEqual:@"a"]){
-            URIString = [URINode getAttribute:@"href"];
+            URIString = [(DOMElement *)URINode getAttribute:@"href"];
         }else{
             URIString = [self fullStringValueIfABBRFromNode:URINode];
         }
@@ -219,11 +218,9 @@
     // get container info:
     // *** NOTE: should do this last, to avoid overwriting data
     
-    NSArray *containerNodes = [citationNode nodesForXPathExpression:[xpaths 
objectForKey:@"container"]];
+    DOMNode *containerNode = [citationNode 
singleNodeForXPathExpression:[xpaths objectForKey:@"container"]];
     
-    if([containerNodes count] > 0) {
-        DOMNode *containerNode = [containerNodes objectAtIndex:0];
-
+    if(containerNode) {
         NSString *citationType = [rd objectForKey:BDSKTypeString];
 
         NSMutableDictionary *containerDict = [NSMutableDictionary 
dictionaryWithDictionary:[self dictionaryFromCitationNode:containerNode 
isContainer:YES xpaths:xpaths]];

Modified: trunk/bibdesk/BDSKIACRParser.m
===================================================================
--- trunk/bibdesk/BDSKIACRParser.m      2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKIACRParser.m      2018-08-23 13:46:51 UTC (rev 22515)
@@ -97,26 +97,27 @@
         authorNodePath = [[self domDocument] createExpression:@".//i" 
resolver:nil];
     }
     
-    for (DOMNode *node in sources) {
+    for (DOMNode *sourceNode in sources) {
                
                NSMutableDictionary *pubFields = [NSMutableDictionary 
dictionary];
                NSArray *filesArray = nil;
         NSString *pathToSearch = nil;
         NSArray *nodes;
+        DOMNode *node;
         NSString *string;
         
         // set title
-        nodes = [node nodesForXPathExpression:titleNodePath];
-        if ([nodes count] && (string = [[nodes firstObject] stringValue]))
+        node = [sourceNode singleNodeForXPathExpression:titleNodePath];
+        if ((string = [node stringValue]))
             [pubFields setObject:string forKey:BDSKTitleString];
         // set authors
-        nodes = [node nodesForXPathExpression:authorNodePath];
-        if ([nodes count] && (string = [[nodes firstObject] stringValue]))
+        node = [sourceNode singleNodeForXPathExpression:authorNodePath];
+        if ((string = [node stringValue]))
             [pubFields setObject:string forKey:BDSKAuthorString];
         // to get year and report number
         if (pathToSearchNodePath) {
-            nodes = [node nodesForXPathExpression:pathToSearchNodePath];
-            if ([nodes count] && (string = [[nodes firstObject] stringValue]))
+            node = [sourceNode 
singleNodeForXPathExpression:pathToSearchNodePath];
+            if ((string = [node stringValue]))
                 pathToSearch = string;
         } else {
             pathToSearch = [url path];

Modified: trunk/bibdesk/BDSKIEEEXploreParser.m
===================================================================
--- trunk/bibdesk/BDSKIEEEXploreParser.m        2018-08-23 13:10:05 UTC (rev 
22514)
+++ trunk/bibdesk/BDSKIEEEXploreParser.m        2018-08-23 13:46:51 UTC (rev 
22515)
@@ -59,7 +59,7 @@
        if ([[url path] isCaseInsensitiveEqual:abstractPageURLPath] || [[url 
path] isCaseInsensitiveEqual:searchResultPageURLPath])
         return YES;
     
-    return [[[domDocument documentElement] 
nodesForXPath:containsAbstractPlusLinkNode] count] > 0;
+    return [[domDocument documentElement] 
singleNodeForXPath:containsAbstractPlusLinkNode] != nil;
 }
 
 - (NSArray *)itemsReturningError:(NSError **)outError {

Modified: trunk/bibdesk/BDSKInspireParser.m
===================================================================
--- trunk/bibdesk/BDSKInspireParser.m   2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKInspireParser.m   2018-08-23 13:46:51 UTC (rev 22515)
@@ -67,9 +67,7 @@
     if ([url hasFirstPathComponent:@"record"])
         return YES;
     
-    NSUInteger nodeCount = [[[domDocument documentElement] nodesForXPath:[self 
citationNodeXPath]] count];
-    
-    return nodeCount > 0;
+    return nil != [[domDocument documentElement] singleNodeForXPath:[self 
citationNodeXPath]];
 }
 
 - (NSArray *)itemsReturningError:(NSError **)outError {
@@ -78,8 +76,8 @@
         NSMutableArray *items = [NSMutableArray array];
         NSString *bibtexString = nil;
         
-        NSArray *preNodes = [[[self domDocument] documentElement] 
nodesForXPath:@"./body/div/div/pre[contains(text(),'@')]"];
-        bibtexString = [[[[preNodes firstObject] textContent] retain] 
autorelease];
+        DOMNode *preNode = [[[self domDocument] documentElement] 
singleNodeForXPath:@"./body/div/div/pre[contains(text(),'@')]"];
+        bibtexString = [[[preNode textContent] retain] autorelease];
         
         NSArray *bibtexItems = nil;
         if (bibtexString)

Modified: trunk/bibdesk/BDSKNumdamParser.m
===================================================================
--- trunk/bibdesk/BDSKNumdamParser.m    2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKNumdamParser.m    2018-08-23 13:46:51 UTC (rev 22515)
@@ -53,9 +53,9 @@
     if ([url hasDomain:@"numdam.org"] == NO)
         return NO;
     
-    NSArray * tableCells = [[domDocument documentElement] 
nodesForXPath:@".//td[@id='contenu']"];
+    DOMNode * tableCell = [[domDocument documentElement] 
singleNodeForXPath:@".//td[@id='contenu']"];
 
-    return [tableCells count] > 0;
+    return tableCell != nil;
 }
 
 // Find references from Zentralblatt Math referred to by the page. Then look 
them up. Insert link to NUMDAM in the item's own record.
@@ -62,8 +62,7 @@
 // (Support for MatSciNet is currently commented out as their lookup script 
requires online-style MR1234567 identifiers and NUMDAM uses paper-style 
identifiers a la 16,957b.)
 - (NSArray *)itemsReturningError:(NSError **)outError {
     
-    NSArray * tableCells = [[[self domDocument] documentElement] 
nodesForXPath:@".//td[@id='contenu']"];
-    DOMNode * tableCell = [tableCells objectAtIndex:0];
+    DOMNode * tableCell = [[[self domDocument] documentElement] 
singleNodeForXPath:@".//td[@id='contenu']"];
     NSString * content = [tableCell textContent];
     
     NSArray * rawReferences = [content componentsSeparatedByString:@"\n"];

Modified: trunk/bibdesk/BDSKProjectEuclidParser.m
===================================================================
--- trunk/bibdesk/BDSKProjectEuclidParser.m     2018-08-23 13:10:05 UTC (rev 
22514)
+++ trunk/bibdesk/BDSKProjectEuclidParser.m     2018-08-23 13:46:51 UTC (rev 
22515)
@@ -53,22 +53,21 @@
     if ([url hasDomain:@"projecteuclid.org"] == NO)
         return NO;
     
-    NSArray * identifiers = [[domDocument documentElement] 
nodesForXPath:@".//div[@id='identifier']/p"];
+    DOMNode * identifier = [[domDocument documentElement] 
singleNodeForXPath:@".//div[@id='identifier']/p"];
 
-       return [identifiers count] > 0;
+       return identifier != nil;
 }
 
 // Find references for Mathematical Reviews and Zentralblatt Math in the page. 
Then look them up, giving preference to MSN if both are available.
 - (NSArray *)itemsReturningError:(NSError **)outError {
 
-       NSArray * identifiers = [[[self domDocument] documentElement] 
nodesForXPath:@".//div[@id='identifier']/p"];
+       DOMNode * identifier = [[[self domDocument] documentElement] 
singleNodeForXPath:@".//div[@id='identifier']/p"];
        
     NSArray *MRRequests = nil;
     NSArray *ZMathRequests = nil;
 
-    if ( [identifiers count] ) {
+    if ( identifier ) {
         
-        DOMNode * identifier = [identifiers objectAtIndex:0];
         NSString * identifierString = [identifier stringValue];
         
         AGRegex * MRRegexp = [AGRegex regexWithPattern:@"MR([1-9][0-9]*)" 
options:0];

Modified: trunk/bibdesk/BDSKSpringerParser.m
===================================================================
--- trunk/bibdesk/BDSKSpringerParser.m  2018-08-23 13:10:05 UTC (rev 22514)
+++ trunk/bibdesk/BDSKSpringerParser.m  2018-08-23 13:46:51 UTC (rev 22515)
@@ -62,7 +62,7 @@
     
     NSString *pubType = BDSKMiscString;
     // set publication type
-    NSString *pubTypeGuess = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='primary']/a/@title"] firstObject] stringValue];
+    NSString *pubTypeGuess = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='primary']/a/@title"] stringValue];
     if (pubTypeGuess != nil) {
         if ([pubTypeGuess isEqualToString:@"Link to the Book of this 
Chapter"]) {
             pubType = BDSKChapterString;
@@ -74,28 +74,28 @@
     }
     
        // set title
-    NSString *title = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
primitive']/div[@class='text']/h1"] firstObject] stringValue];
+    NSString *title = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
primitive']/div[@class='text']/h1"] stringValue];
     if (title != nil)
         [pubFields setObject:title forKey:BDSKTitleString];
        
     // set book or journal
     if ([pubType isEqualToString:BDSKChapterString]) {
-        NSString *chapter = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='primary']/a"] firstObject] stringValue];
+        NSString *chapter = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='primary']/a"] stringValue];
         if (chapter != nil)
             [pubFields setObject:chapter forKey:BDSKBooktitleString];
     } else if ([pubType isEqualToString:BDSKArticleString]) {
-        NSString *journal = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='primary']/a"] firstObject] stringValue];
+        NSString *journal = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='primary']/a"] stringValue];
         if (journal != nil)
             [pubFields setObject:journal forKey:BDSKJournalString];
     }
     
        // set DOI and store for later use
-    NSString *doi = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']//span[@class='doi']/span[@class='value']"] firstObject] 
stringValue];
+    NSString *doi = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']//span[@class='doi']/span[@class='value']"] stringValue];
     if (doi != nil)
         [pubFields setObject:doi forKey:BDSKDoiString];
 
        // set pages
-    NSString *pages = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']//span[@class='pagination']"] firstObject] stringValue];
+    NSString *pages = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']//span[@class='pagination']"] stringValue];
     if (pages != nil) {
         AGRegex *pagesRegex = [AGRegex 
regexWithPattern:@"^([0-9]*)-([0-9]*)?"];
         AGRegexMatch *match = [pagesRegex findInString:pages];
@@ -122,13 +122,13 @@
         [pubFields setValue:editors forKey:BDSKEditorString];
        // set series
     if ([pubType isEqualToString:BDSKChapterString]) {
-        NSString *series = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='secondary']/a"] firstObject] stringValue];
+        NSString *series = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='secondary']/a"] stringValue];
         if (series != nil)
             [pubFields setObject:series forKey:BDSKSeriesString];
     }
     
     // volume, number, and year
-    NSString *vyString = [[[node 
nodesForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='secondary']"] firstObject] stringValue];
+    NSString *vyString = [[node 
singleNodeForXPath:@".//div[@id='ContentHeading']/div[@class='heading 
enumeration']/div[@class='secondary']"] stringValue];
     if (vyString != nil) {
         // parse volume number
                AGRegex *volRegex = [AGRegex regexWithPattern:@"Volume 
([0-9]*)[^0-9]"];

Modified: trunk/bibdesk/DOMNode_BDSKExtensions.h
===================================================================
--- trunk/bibdesk/DOMNode_BDSKExtensions.h      2018-08-23 13:10:05 UTC (rev 
22514)
+++ trunk/bibdesk/DOMNode_BDSKExtensions.h      2018-08-23 13:46:51 UTC (rev 
22515)
@@ -42,7 +42,9 @@
 @interface DOMNode (BDSKExtensions)
 
 - (NSArray *)nodesForXPath:(NSString *)xpath;
+- (DOMNode *)singleNodeForXPath:(NSString *)xpath;
 - (NSArray *)nodesForXPathExpression:(DOMXPathExpression *)xpathExpression;
+- (DOMNode *)singleNodeForXPathExpression:(DOMXPathExpression 
*)xpathExpression;
 
 - (NSString *)stringValue;
 - (NSString *)stringValuePreservingBreaks;

Modified: trunk/bibdesk/DOMNode_BDSKExtensions.m
===================================================================
--- trunk/bibdesk/DOMNode_BDSKExtensions.m      2018-08-23 13:10:05 UTC (rev 
22514)
+++ trunk/bibdesk/DOMNode_BDSKExtensions.m      2018-08-23 13:46:51 UTC (rev 
22515)
@@ -56,6 +56,11 @@
     return nodes;
 }
 
+- (DOMNode *)singleNodeForXPath:(NSString *)xpath {
+    DOMXPathResult *result = [[self ownerDocument] evaluate:xpath 
contextNode:self resolver:nil type:DOM_FIRST_ORDERED_NODE_TYPE inResult:nil];
+    return [result singleNodeValue];
+}
+
 - (NSArray *)nodesForXPathExpression:(DOMXPathExpression *)xpathExpression {
     if (xpathExpression == nil)
         return nil;
@@ -74,6 +79,14 @@
     return nodes;
 }
 
+- (DOMNode *)singleNodeForXPathExpression:(DOMXPathExpression 
*)xpathExpression {
+    if (xpathExpression == nil)
+        return nil;
+    
+    DOMXPathResult *result = [xpathExpression evaluate:self 
type:DOM_FIRST_ORDERED_NODE_TYPE inResult:nil];
+    return [result singleNodeValue];
+}
+
 // DOM keeps all spaces and newlines as in the html, rather than as they are 
interpreted
 - (NSString *)stringValue {
     return [[self textContent] 
stringByCollapsingWhitespaceAndNewlinesAndRemovingSurroundingWhitespaceAndNewlines]
 ?: @"";

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit

Reply via email to