Add implementation for HTML Node Tree Enumerator
Tree-Order (pre-order) enumeration for HTML Node and its descendants
This commit is contained in:
@@ -46,6 +46,11 @@
|
||||
6238C9851AB8D6330006512E /* HTMLKitExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238C9831AB8D6330006512E /* HTMLKitExceptions.h */; };
|
||||
6238C9861AB8D6330006512E /* HTMLKitExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitExceptions.m */; };
|
||||
6238C9871AB8D6330006512E /* HTMLKitExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitExceptions.m */; };
|
||||
623916C31AC707250066B4FE /* HTMLNodeTreeEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 623916C11AC707250066B4FE /* HTMLNodeTreeEnumerator.h */; };
|
||||
623916C41AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */; };
|
||||
623916C51AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */; };
|
||||
623916C71AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */; };
|
||||
623916C81AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */; };
|
||||
624493A619CCC54100BCDDF4 /* HTMLTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A419CCC54100BCDDF4 /* HTMLTokenizer.h */; };
|
||||
624493A719CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */; };
|
||||
624493A819CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */; };
|
||||
@@ -163,6 +168,9 @@
|
||||
6238579A1A9E8934003A45D9 /* HTMLComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLComment.m; sourceTree = "<group>"; };
|
||||
6238C9831AB8D6330006512E /* HTMLKitExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLKitExceptions.h; sourceTree = "<group>"; };
|
||||
6238C9841AB8D6330006512E /* HTMLKitExceptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitExceptions.m; sourceTree = "<group>"; };
|
||||
623916C11AC707250066B4FE /* HTMLNodeTreeEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeTreeEnumerator.h; sourceTree = "<group>"; };
|
||||
623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeTreeEnumerator.m; sourceTree = "<group>"; };
|
||||
623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodeTreeEnumratorTests.m; sourceTree = "<group>"; };
|
||||
624493A419CCC54100BCDDF4 /* HTMLTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizer.h; sourceTree = "<group>"; };
|
||||
624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTokenizer.m; sourceTree = "<group>"; };
|
||||
624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerStates.h; sourceTree = "<group>"; };
|
||||
@@ -282,6 +290,8 @@
|
||||
6238579A1A9E8934003A45D9 /* HTMLComment.m */,
|
||||
62362A3A1A9FA70400301989 /* HTMLText.h */,
|
||||
62362A3B1A9FA70400301989 /* HTMLText.m */,
|
||||
623916C11AC707250066B4FE /* HTMLNodeTreeEnumerator.h */,
|
||||
623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */,
|
||||
);
|
||||
name = Nodes;
|
||||
sourceTree = "<group>";
|
||||
@@ -372,6 +382,7 @@
|
||||
625A14CA19C7829400AD0C32 /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */,
|
||||
6236738C1AC0CD2400FF89B3 /* Tokenizer */,
|
||||
625A14CB19C7829400AD0C32 /* Supporting Files */,
|
||||
);
|
||||
@@ -430,6 +441,7 @@
|
||||
6235CE9B1AA509430026937B /* NSString+HTMLKit.h in Headers */,
|
||||
62F873EB19E088C90062683C /* HTMLParser.h in Headers */,
|
||||
624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */,
|
||||
623916C31AC707250066B4FE /* HTMLNodeTreeEnumerator.h in Headers */,
|
||||
62AE594419F992F30043F069 /* HTMLCommentToken.h in Headers */,
|
||||
624493AC19CD0CBE00BCDDF4 /* HTMLToken.h in Headers */,
|
||||
6235CEA01AA5170A0026937B /* HTMLMarker.h in Headers */,
|
||||
@@ -611,6 +623,7 @@
|
||||
62AE594119F9907C0043F069 /* HTMLTagToken.m in Sources */,
|
||||
62AE594619F992F30043F069 /* HTMLCommentToken.m in Sources */,
|
||||
62363C3F1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */,
|
||||
623916C51AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */,
|
||||
62AE593C19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */,
|
||||
6238C9871AB8D6330006512E /* HTMLKitExceptions.m in Sources */,
|
||||
62F873ED19E088C90062683C /* HTMLParser.m in Sources */,
|
||||
@@ -634,6 +647,7 @@
|
||||
files = (
|
||||
6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */,
|
||||
624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */,
|
||||
623916C81AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */,
|
||||
62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -652,6 +666,7 @@
|
||||
62AE594019F9907C0043F069 /* HTMLTagToken.m in Sources */,
|
||||
62AE594519F992F30043F069 /* HTMLCommentToken.m in Sources */,
|
||||
62363C3E1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */,
|
||||
623916C41AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */,
|
||||
62AE593B19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */,
|
||||
6238C9861AB8D6330006512E /* HTMLKitExceptions.m in Sources */,
|
||||
62F873EC19E088C90062683C /* HTMLParser.m in Sources */,
|
||||
@@ -675,6 +690,7 @@
|
||||
files = (
|
||||
6236738E1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */,
|
||||
624AC90119FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */,
|
||||
623916C71AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */,
|
||||
62D8345919FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
@@ -77,4 +77,7 @@ typedef NS_ENUM(short, HTMLNodeType)
|
||||
|
||||
- (HTMLNode *)removeChildNodeAtIndex:(NSUInteger)index;
|
||||
|
||||
- (NSEnumerator *)treeEnumerator;
|
||||
- (NSEnumerator *)reverseTreeEnumerator;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import "HTMLDocument.h"
|
||||
#import "HTMLElement.h"
|
||||
#import "HTMLKitExceptions.h"
|
||||
#import "HTMLNodeTreeEnumerator.h"
|
||||
|
||||
@interface HTMLNode ()
|
||||
{
|
||||
@@ -180,6 +181,18 @@
|
||||
return [self removeChildNode:node];
|
||||
}
|
||||
|
||||
#pragma mark - Enumeration
|
||||
|
||||
- (NSEnumerator *)treeEnumerator
|
||||
{
|
||||
return [[HTMLNodeTreeEnumerator alloc] initWithNode:self reverse:NO];
|
||||
}
|
||||
|
||||
- (NSEnumerator *)reverseTreeEnumerator
|
||||
{
|
||||
return [[HTMLNodeTreeEnumerator alloc] initWithNode:self reverse:YES];
|
||||
}
|
||||
|
||||
#pragma mark - Mutation Algorithms
|
||||
|
||||
- (HTMLNode *)preInsertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// HTMLNodeTreeEnumerator.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class HTMLNode;
|
||||
|
||||
@interface HTMLNodeTreeEnumerator : NSEnumerator
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node reverse:(BOOL)reverse;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// HTMLNodeTreeEnumerator.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HTMLNodeTreeEnumerator.h"
|
||||
#import "HTMLNode.h"
|
||||
|
||||
@interface HTMLNodeTreeEnumerator ()
|
||||
{
|
||||
BOOL _reverse;
|
||||
NSMutableArray *_stack;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation HTMLNodeTreeEnumerator
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node reverse:(BOOL)reverse
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_reverse = reverse;
|
||||
_stack = [[NSMutableArray alloc] initWithObjects:node, nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)nextObject
|
||||
{
|
||||
if (_stack.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
HTMLNode *node = _stack.lastObject;
|
||||
[_stack removeLastObject];
|
||||
|
||||
NSArray *childNodes = node.childNodes.array;
|
||||
if (childNodes != nil && childNodes.count > 0) {
|
||||
if (childNodes.count > 1) {
|
||||
NSRange range = NSMakeRange(_reverse ? 0 : 1, childNodes.count - 1);
|
||||
NSArray *rest = [childNodes subarrayWithRange:range];
|
||||
|
||||
[_stack addObjectsFromArray:_reverse ? rest : rest.reverseObjectEnumerator.allObjects];
|
||||
}
|
||||
[_stack addObject:_reverse ? childNodes.lastObject : childNodes.firstObject];
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// HTMLKitNodeTreeEnumratorTests.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "HTMLNodes.h"
|
||||
|
||||
@interface HTMLKitNodeTreeEnumratorTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation HTMLKitNodeTreeEnumratorTests
|
||||
|
||||
#pragma mark - Elements
|
||||
|
||||
- (HTMLElement *)div
|
||||
{
|
||||
return [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
}
|
||||
|
||||
- (HTMLElement *)simpleTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"a"]];
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"b"]];
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"c"]];
|
||||
return div;
|
||||
}
|
||||
|
||||
- (HTMLElement *)nestedSimpleTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:self.simpleTree];
|
||||
[div appendNode:self.simpleTree];
|
||||
return div;
|
||||
}
|
||||
|
||||
- (HTMLElement *)complexTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| div
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
| e
|
||||
| f
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *root = self.div;
|
||||
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:self.simpleTree];
|
||||
[root appendNode:div];
|
||||
|
||||
HTMLElement *e = [[HTMLElement alloc] initWithTagName:@"e"];
|
||||
[e appendNode:[[HTMLElement alloc] initWithTagName:@"f"]];
|
||||
[root appendNode:e];
|
||||
[root appendNode:self.simpleTree];
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
#pragma mark - Tests
|
||||
|
||||
- (void)testSingle
|
||||
{
|
||||
HTMLElement *div = self.div;
|
||||
NSArray *result = div.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testSimpleTree
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
NSArray *result = tree.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testSimpleTreeReversed
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
NSArray *result = tree.reverseTreeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"c", @"b", @"a"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testNestedSimpleTree
|
||||
{
|
||||
HTMLElement *tree = self.nestedSimpleTree;
|
||||
NSArray *result = tree.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div", @"a", @"b", @"c", @"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testNestedSimpleTreeReversed
|
||||
{
|
||||
HTMLElement *tree = self.nestedSimpleTree;
|
||||
NSArray *result = tree.reverseTreeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div", @"c", @"b", @"a", @"div", @"c", @"b", @"a"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testComplexSimpleTree
|
||||
{
|
||||
HTMLElement *tree = self.complexTree;
|
||||
NSArray *result = tree.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div",@"div", @"a", @"b", @"c", @"e", @"f", @"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testComplexSimpleTreeReversed
|
||||
{
|
||||
HTMLElement *tree = self.complexTree;
|
||||
NSArray *result = tree.reverseTreeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div", @"c", @"b", @"a", @"e", @"f", @"div", @"div", @"c", @"b", @"a"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user