Reintroduce the HTMLNodeFilterValue for Tree Walker implementation
While the Node Iterator treats skip & reject the same way, the Tree Walker can skip over a node
and all its children if rejected.
This reverses dc3de7a470
This commit is contained in:
+1
-1
@@ -119,7 +119,7 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition)
|
||||
- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(id<HTMLNodeFilter>)filter;
|
||||
- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filterBlock:(BOOL (^)(HTMLNode *node))filter;
|
||||
filterBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))filter;
|
||||
|
||||
- (NSString *)treeDescription;
|
||||
|
||||
|
||||
+1
-1
@@ -381,7 +381,7 @@
|
||||
}
|
||||
|
||||
- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filterBlock:(BOOL (^)(HTMLNode *node))filter
|
||||
filterBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))filter
|
||||
{
|
||||
return [HTMLNodeIterator iteratorWithNode:self showOptions:showOptions filter:filter];
|
||||
}
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(unsigned short, HTMLNodeFilterValue)
|
||||
{
|
||||
HTMLNodeFilterAccept = 1,
|
||||
HTMLNodeFilterReject = 2,
|
||||
HTMLNodeFilterSkip = 3
|
||||
};
|
||||
|
||||
typedef NS_ENUM(unsigned long, HTMLNodeFilterShowOptions)
|
||||
{
|
||||
HTMLNodeFilterShowAll = 0xFFFFFFFF,
|
||||
@@ -23,12 +30,12 @@ typedef NS_ENUM(unsigned long, HTMLNodeFilterShowOptions)
|
||||
|
||||
@protocol HTMLNodeFilter <NSObject>
|
||||
|
||||
- (BOOL)acceptNode:(HTMLNode *)node;
|
||||
- (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node;
|
||||
|
||||
@end
|
||||
|
||||
@interface HTMLNodeFilterBlock : NSObject <HTMLNodeFilter>
|
||||
|
||||
+ (instancetype)filterWithBlock:(BOOL (^)(HTMLNode *node))block;
|
||||
+ (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))block;
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
@implementation HTMLNodeFilterBlock
|
||||
|
||||
+ (instancetype)filterWithBlock:(BOOL (^)(HTMLNode *))block
|
||||
+ (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *))block
|
||||
{
|
||||
return [[self alloc] initWithBlock:block];
|
||||
}
|
||||
|
||||
- (instancetype)initWithBlock:(BOOL (^)(HTMLNode *))block
|
||||
- (instancetype)initWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *))block
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
@@ -30,10 +30,10 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)acceptNode:(HTMLNode *)node
|
||||
- (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node
|
||||
{
|
||||
if (!_block) {
|
||||
return NO;
|
||||
return HTMLNodeFilterSkip;
|
||||
}
|
||||
|
||||
return _block(node);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
+ (instancetype)iteratorWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(BOOL (^)(HTMLNode *node))filter;
|
||||
filter:(HTMLNodeFilterValue (^)(HTMLNode *node))filter;
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node;
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
|
||||
@@ -35,7 +35,7 @@ typedef NS_ENUM(short, TraverseDirection)
|
||||
|
||||
+ (instancetype)iteratorWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(BOOL (^)(HTMLNode *))filter
|
||||
filter:(HTMLNodeFilterValue (^)(HTMLNode *))filter
|
||||
{
|
||||
return [[self alloc] initWithNode:node
|
||||
showOptions:showOptions
|
||||
@@ -139,7 +139,7 @@ typedef NS_ENUM(short, TraverseDirection)
|
||||
}
|
||||
beforeNode = YES;
|
||||
}
|
||||
} while (!FilterNode(self.filter, self.whatToShow, node));
|
||||
} while (FilterNode(self.filter, self.whatToShow, node) != HTMLNodeFilterAccept);
|
||||
|
||||
_referenceNode = node;
|
||||
_pointerBeforeReferenceNode = beforeNode;
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
extern HTMLNode * PrecedingNode(HTMLNode *node, HTMLNode *root);
|
||||
extern HTMLNode * FollowingNode(HTMLNode *node, HTMLNode *root);
|
||||
extern HTMLNode * FollowingNodeSkippingChildren(HTMLNode *node, HTMLNode *root);
|
||||
extern BOOL FilterNode(id<HTMLNodeFilter> filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node);
|
||||
extern HTMLNodeFilterValue FilterNode(id<HTMLNodeFilter> filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node);
|
||||
|
||||
@@ -61,15 +61,15 @@ HTMLNode * FollowingNodeSkippingChildren(HTMLNode *node, HTMLNode *root)
|
||||
return nil;
|
||||
}
|
||||
|
||||
BOOL FilterNode(id<HTMLNodeFilter> filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node)
|
||||
HTMLNodeFilterValue FilterNode(id<HTMLNodeFilter> filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node)
|
||||
{
|
||||
unsigned long nthBit = (1 << (node.nodeType - 1)) & whatToShow;
|
||||
if (!nthBit) {
|
||||
return NO;
|
||||
return HTMLNodeFilterSkip;
|
||||
}
|
||||
|
||||
if (filter == nil) {
|
||||
return YES;
|
||||
return HTMLNodeFilterAccept;
|
||||
}
|
||||
|
||||
return [filter acceptNode:node];
|
||||
|
||||
+34
-31
@@ -43,6 +43,20 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
|
||||
#pragma mark - Traversal
|
||||
|
||||
- (HTMLNode *)parentNode
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
while (node != nil && node != _root) {
|
||||
node = node.parentNode;
|
||||
if (node != nil && FilterNode(self.filter, self.whatToShow, node) == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)traverseChildrenOfType:(HTMLTreeWalkerChildrenType)type
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
@@ -50,16 +64,18 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
node = (type == HTMLTreeWalkerChildrenTypeFirst) ? node.firstChiledNode : node.lastChildNode;
|
||||
|
||||
while (node != nil) {
|
||||
BOOL result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result) {
|
||||
HTMLNodeFilterValue result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
HTMLNode *child = (type == HTMLTreeWalkerChildrenTypeFirst) ? node.firstChiledNode : node.lastChildNode;
|
||||
if (child != nil) {
|
||||
node = child;
|
||||
continue;
|
||||
if (result == HTMLNodeFilterSkip) {
|
||||
HTMLNode *child = (type == HTMLTreeWalkerChildrenTypeFirst) ? node.firstChiledNode : node.lastChildNode;
|
||||
if (child != nil) {
|
||||
node = child;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (node != nil) {
|
||||
@@ -80,20 +96,6 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)parentNode
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
while (node != nil && node != _root) {
|
||||
node = node.parentNode;
|
||||
if (node != nil && FilterNode(self.filter, self.whatToShow, node)) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)firstChild
|
||||
{
|
||||
return [self traverseChildrenOfType:HTMLTreeWalkerChildrenTypeFirst];
|
||||
@@ -116,8 +118,8 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
HTMLNode *sibling = (type == HTMLTreeWalkerSiblingsTypeNext) ? node.nextSibling : node.previousSibling;
|
||||
while (sibling != nil) {
|
||||
node = sibling;
|
||||
BOOL result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result) {
|
||||
HTMLNodeFilterValue result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
@@ -133,10 +135,11 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (FilterNode(self.filter, self.whatToShow, node)) {
|
||||
if (FilterNode(self.filter, self.whatToShow, node) == HTMLNodeFilterAccept) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -160,13 +163,13 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
while (sibling != nil) {
|
||||
node = sibling;
|
||||
|
||||
BOOL result = FilterNode(self.filter, self.whatToShow, node);
|
||||
while (result && node.hasChildNodes) {
|
||||
HTMLNodeFilterValue result = FilterNode(self.filter, self.whatToShow, node);
|
||||
while (result != HTMLNodeFilterReject && node.hasChildNodes) {
|
||||
node = node.lastChildNode;
|
||||
result = FilterNode(self.filter, self.whatToShow, node);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
@@ -179,7 +182,7 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
}
|
||||
|
||||
node = node.parentNode;
|
||||
if (FilterNode(self.filter, self.whatToShow, node)) {
|
||||
if (FilterNode(self.filter, self.whatToShow, node) == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
@@ -192,13 +195,13 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
BOOL result = YES;
|
||||
HTMLNodeFilterValue result = YES;
|
||||
|
||||
while (YES) {
|
||||
while (!result && node.hasChildNodes) {
|
||||
while (result != HTMLNodeFilterReject && node.hasChildNodes) {
|
||||
node = node.firstChiledNode;
|
||||
result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result) {
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
@@ -208,7 +211,7 @@ typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
while ((nextSibling = FollowingNodeSkippingChildren(node, _root)) != nil) {
|
||||
node = nextSibling;
|
||||
result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result) {
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -310,13 +310,14 @@
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowAll filterBlock:^BOOL(HTMLNode *node) {
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowAll
|
||||
filterBlock:^HTMLNodeFilterValue(HTMLNode *node) {
|
||||
if (node.nodeType == HTMLNodeComment) {
|
||||
if ([[(HTMLComment *)node data] rangeOfString:@"second"].location != NSNotFound) {
|
||||
return YES;
|
||||
return HTMLNodeFilterAccept;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
return HTMLNodeFilterSkip;
|
||||
}];
|
||||
|
||||
NSArray *result = iterator.allObjects;
|
||||
|
||||
Reference in New Issue
Block a user