18 Commits

Author SHA1 Message Date
iska d756fc4298 Merge branch 'release/2.1.5' 2018-07-16 22:13:29 +02:00
iska 7c2335184e Bump HTMLKit version to 2.1.5 2018-07-16 22:13:21 +02:00
iska 0c6084ba73 Update podspec for 2.1.4 2018-07-16 22:12:54 +02:00
iska 5201860073 Add Changelog entry for HTMLKit 2.1.5 2018-07-16 22:12:39 +02:00
iska cf21b88eb1 Add Changelog entry for HTMLKit 2.1.5 2018-07-16 22:12:30 +02:00
iska 7617fceff1 Add test for bug fix issue #30 2018-07-16 22:09:35 +02:00
iska 9dd3c70fc3 Remove foreign attributes adjustment
Fixes #30

Foreign attributes were handled incorrectly because attribute names
were implemented as pure strings without namespace prefix. This change
keeps the attributes as strings and eliminates any handling in regards
to namespaces.

Spec note about attributes:
"If designed today they would just have a name and value."

https://dom.spec.whatwg.org/#attr
2018-05-10 18:41:54 +02:00
Iskandar Abudiab fe2a441171 Merge pull request #29 from CRivlaldo/develop
Fix the issue 28
2018-05-03 20:11:33 +02:00
Vladimir Vlasov 7c32b5f219 Fix the issue 28 2018-05-03 19:00:29 +03:00
iska bf0d8560b0 Merge branch 'release/2.1.4' 2018-05-01 20:08:30 +02:00
iska ebc6f7a097 Merge branch 'release/2.1.4' into develop 2018-05-01 20:08:30 +02:00
iska d29a70dfec Bump HTMLKit version to 2.1.4 2018-05-01 20:08:00 +02:00
iska b8f56ca97d Update podspec for 2.1.4 2018-05-01 20:07:44 +02:00
iska 0f954d5d56 Update jazzy.yaml for 2.1.4 2018-05-01 20:07:35 +02:00
iska ac5089d69b Add Changelog entry for HTMLKit 2.1.4 2018-05-01 20:07:23 +02:00
iska c9c36397e0 Update CocoaPods block in Readme 2018-05-01 20:02:36 +02:00
iska 923e271429 Fix eq, lt & gt selectors for the zero-index case
Fixes #25
2018-04-18 23:51:39 +02:00
iska da765169fa Merge branch 'release/2.1.3' into develop 2018-03-21 22:51:46 +01:00
14 changed files with 152 additions and 41 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
module: HTMLKit
module_version: 2.1.3
module_version: 2.1.5
author: Iskandar Abudiab
author_url: https://twitter.com/iabudiab
github_url: https://github.com/iabudiab/HTMLKit
+18
View File
@@ -1,5 +1,23 @@
# Change Log
## [2.1.5](https://github.com/iabudiab/HTMLKit/releases/tag/2.1.5)
Released on 2018.07.16
### Fixes
- Parser would handle foreign attributes incorrectly (issue #30)
## [2.1.4](https://github.com/iabudiab/HTMLKit/releases/tag/2.1.4)
Released on 2018.05.01
### Fixes
- `gt(n)`, `lt(n)` and `eq(n)` selectors would select wrong elements for the zero-index (issue #25)
## [2.1.3](https://github.com/iabudiab/HTMLKit/releases/tag/2.1.3)
Released on 2018.03.21
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "HTMLKit"
s.version = "2.1.3"
s.version = "2.1.5"
s.summary = "HTMLKit, an Objective-C framework for your everyday HTML needs."
s.license = "MIT"
s.homepage = "https://github.com/iabudiab/HTMLKit"
+24
View File
@@ -11,6 +11,9 @@
62056C501E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
62056C511E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
62056C521E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
620AB7B12087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 620AB7B02087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m */; };
620AB7B22087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 620AB7B02087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m */; };
620AB7B32087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 620AB7B02087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m */; };
62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62132E581C01F83200084175 /* CSSSelectorTest.m */; };
62132E5D1C021FF200084175 /* css-tests in Resources */ = {isa = PBXBuildFile; fileRef = 62132E5B1C021FF200084175 /* css-tests */; };
6216ACFD1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */; };
@@ -309,6 +312,9 @@
62A95A4D1FB0FBFC0009FF26 /* HTMLSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62A95A4C1FB0FBFC0009FF26 /* HTMLSerializationTests.m */; };
62A95A4E1FB0FBFC0009FF26 /* HTMLSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62A95A4C1FB0FBFC0009FF26 /* HTMLSerializationTests.m */; };
62A95A4F1FB0FBFC0009FF26 /* HTMLSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62A95A4C1FB0FBFC0009FF26 /* HTMLSerializationTests.m */; };
62C82E0D20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62C82E0C20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m */; };
62C82E0E20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62C82E0C20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m */; };
62C82E0F20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62C82E0C20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m */; };
62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */; };
62D91C231DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; settings = {ATTRIBUTES = (Public, ); }; };
62D91C241DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -584,6 +590,7 @@
/* Begin PBXFileReference section */
62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLNodeIterator+Private.h"; path = "include/HTMLNodeIterator+Private.h"; sourceTree = "<group>"; };
62079BE71AF56F1E00D3B402 /* CSSSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSSelector.h; path = include/CSSSelector.h; sourceTree = "<group>"; };
620AB7B02087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CSSStructuralPseudoSelectors.m; path = HTMLKitTests/CSSStructuralPseudoSelectors.m; sourceTree = "<group>"; };
620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSCompoundSelector.h; path = include/CSSCompoundSelector.h; sourceTree = "<group>"; };
620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCompoundSelector.m; sourceTree = "<group>"; };
620EE9471BC46F2A0028ED34 /* CSSPseudoClassSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSPseudoClassSelector.h; path = include/CSSPseudoClassSelector.h; sourceTree = "<group>"; };
@@ -719,6 +726,7 @@
62AE594319F992F30043F069 /* HTMLCommentToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCommentToken.m; sourceTree = "<group>"; };
62AE594719F9948A0043F069 /* HTMLCharacterToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLCharacterToken.h; path = include/HTMLCharacterToken.h; sourceTree = "<group>"; };
62AE594819F9948A0043F069 /* HTMLCharacterToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterToken.m; sourceTree = "<group>"; };
62C82E0C20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = HTMLKitParserIssuesTests.m; path = HTMLKitTests/HTMLKitParserIssuesTests.m; sourceTree = "<group>"; };
62D8345719FB1AC4009205A9 /* HTML5LibTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTML5LibTokenizerTest.h; path = HTMLKitTests/HTML5LibTokenizerTest.h; sourceTree = "<group>"; };
62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTML5LibTokenizerTest.m; path = HTMLKitTests/HTML5LibTokenizerTest.m; sourceTree = "<group>"; };
62D91C211DE218A500BEFADE /* HTMLRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLRange.h; path = include/HTMLRange.h; sourceTree = "<group>"; };
@@ -989,6 +997,7 @@
625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */,
6236738C1AC0CD2400FF89B3 /* Tokenizer */,
623975581AC362A5007E26F1 /* Tree Construction */,
62C82E0B20FD2FCB008497A8 /* Parser */,
624B9FB71AE072CB00646C4C /* DOM */,
624B9FB81AE072D500646C4C /* Categories */,
624E1A2D1B1D1C8A00E66AAC /* Structures */,
@@ -1093,6 +1102,14 @@
name = Tokenizing;
sourceTree = "<group>";
};
62C82E0B20FD2FCB008497A8 /* Parser */ = {
isa = PBXGroup;
children = (
62C82E0C20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m */,
);
name = Parser;
sourceTree = "<group>";
};
62ECBEDF1C0B671000AF847B /* Parsing */ = {
isa = PBXGroup;
children = (
@@ -1144,6 +1161,7 @@
624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */,
62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */,
621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */,
620AB7B02087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m */,
);
name = Selectors;
sourceTree = "<group>";
@@ -1750,8 +1768,10 @@
buildActionMask = 2147483647;
files = (
62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */,
620AB7B12087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m in Sources */,
62E0BA971E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */,
6216ACFD1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */,
62C82E0D20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m in Sources */,
62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */,
6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */,
62F658711BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m in Sources */,
@@ -1893,8 +1913,10 @@
buildActionMask = 2147483647;
files = (
62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */,
620AB7B32087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m in Sources */,
62E0BA991E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */,
62857D3B1D39A345008DC254 /* CSSSelectorTest.m in Sources */,
62C82E0F20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m in Sources */,
62857D421D39A345008DC254 /* CSSCombinatorSelectorTests.m in Sources */,
62857D3C1D39A345008DC254 /* CSSSelectorParserTests.m in Sources */,
62857D301D39A339008DC254 /* HTMLKitTokenizerPerformance.m in Sources */,
@@ -1981,8 +2003,10 @@
buildActionMask = 2147483647;
files = (
62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */,
620AB7B22087F18D00AFCCC7 /* CSSStructuralPseudoSelectors.m in Sources */,
62E0BA981E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */,
6216ACFE1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */,
62C82E0E20FD2FFD008497A8 /* HTMLKitParserIssuesTests.m in Sources */,
62ECBFCA1C0B6E2E00AF847B /* HTML5LibTokenizerTest.m in Sources */,
62ECBFCB1C0B6E2E00AF847B /* HTMLKitTokenizerTests.m in Sources */,
62ECBFCC1C0B6E2E00AF847B /* HTMLKitTokenizerPerformance.m in Sources */,
+1 -3
View File
@@ -76,10 +76,8 @@ $ gem install cocoapods
To add `HTMLKit` as a dependency into your project using CocoaPods just add the following in your `Podfile`:
```ruby
use_frameworks!
target 'MyTarget' do
pod 'HTMLKit', '~> 2.0'
pod 'HTMLKit', '~> 2.1'
end
```
+3 -3
View File
@@ -276,7 +276,7 @@ CSSSelector * ltSelector(NSInteger index)
return namedBlockSelector(name, ^BOOL(HTMLElement * _Nonnull element) {
NSUInteger elementIndex = [element.parentElement indexOfChildNode:element];
if (index > 0) {
if (index >= 0) {
return elementIndex < index;
} else {
return elementIndex < element.parentElement.childNodesCount - index - 1;
@@ -290,7 +290,7 @@ CSSSelector * gtSelector(NSInteger index)
return namedBlockSelector(name, ^BOOL(HTMLElement * _Nonnull element) {
NSUInteger elementIndex = [element.parentElement indexOfChildNode:element];
if (index > 0) {
if (index >= 0) {
return elementIndex > index;
} else {
return elementIndex > element.parentElement.childNodesCount - index - 1;
@@ -304,7 +304,7 @@ CSSSelector * eqSelector(NSInteger index)
return namedBlockSelector(name, ^BOOL(HTMLElement * _Nonnull element) {
NSUInteger elementIndex = [element.parentElement indexOfChildNode:element];
if (index > 0) {
if (index >= 0) {
return elementIndex == index;
} else {
return elementIndex == element.parentElement.childNodesCount - index - 1;
+1 -1
View File
@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.1.3</string>
<string>2.1.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+1 -1
View File
@@ -127,7 +127,7 @@ NSString * const RemoveChildNode = @"-removeChildNode:";
- (HTMLElement *)nextSiblingElement
{
HTMLNode *node = self.previousSibling;
HTMLNode *node = self.nextSibling;
while (node && node.nodeType != HTMLNodeElement) {
node = node.nextSibling;
}
-3
View File
@@ -1443,7 +1443,6 @@
} else if ([tagName isEqualToString:@"math"]) {
[self reconstructActiveFormattingElements];
AdjustMathMLAttributes(token);
AdjustForeignAttributes(token);
[self insertForeignElementForToken:token inNamespace:HTMLNamespaceMathML];
if (token.isSelfClosing) {
[_stackOfOpenElements popCurrentNode];
@@ -1451,7 +1450,6 @@
} else if ([tagName isEqualToString:@"svg"]) {
[self reconstructActiveFormattingElements];
AdjustSVGAttributes(token);
AdjustForeignAttributes(token);
[self insertForeignElementForToken:token inNamespace:HTMLNamespaceSVG];
if (token.isSelfClosing) {
[_stackOfOpenElements popCurrentNode];
@@ -2541,7 +2539,6 @@
AdjustSVGNameCase(token.asTagToken);
AdjustSVGAttributes(token.asTagToken);
}
AdjustForeignAttributes(token.asTagToken);
[self insertForeignElementForToken:token.asTagToken inNamespace:self.adjustedCurrentNode.htmlNamespace];
if (token.asTagToken.selfClosing) {
[_stackOfOpenElements popCurrentNode];
-28
View File
@@ -140,31 +140,3 @@ NS_INLINE void AdjustSVGNameCase(HTMLTagToken *token)
NSString *replacement = replacements[token.tagName] ?: token.tagName;
token.tagName = replacement;
}
NS_INLINE void AdjustForeignAttributes(HTMLTagToken *token)
{
if (token.attributes == nil) {
return;
}
NSDictionary *replacements = @{ @"xlink:actuate": @"xlink actuate",
@"xlink:arcrole": @"xlink arcrole",
@"xlink:href": @"xlink href",
@"xlink:role": @"xlink role",
@"xlink:show": @"xlink show",
@"xlink:title": @"xlink title",
@"xlink:type": @"xlink type",
@"xml:base": @"xml base",
@"xml:lang": @"xml lang",
@"xml:space": @"xml space",
@"xmlns": @"xmlns",
@"xmlns:xlink": @"xmlns xlink"};
HTMLOrderedDictionary *adjusted = [HTMLOrderedDictionary new];
for (id key in token.attributes) {
NSString *replacement = replacements[key] ?: key;
adjusted[replacement] = token.attributes[key];
}
token.attributes = adjusted;
}
@@ -0,0 +1,41 @@
//
// CSSStructuralPseudoSelectors.m
// HTMLKit
//
// Created by Iska on 18.04.18.
// Copyright © 2018 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "CSSSelectors.h"
#import "HTMLParser.h"
#import "HTMLDOM.h"
@interface CSSStructuralPseudoSelectors : XCTestCase
@end
@implementation CSSStructuralPseudoSelectors
#pragma mark - Bug Fixes
- (void)testBugFix_Issue_25
{
NSString *html = @"<table><tr><td>TD #0</td><td>TD #1</td><td>TD #2</td><td>TD #3</td></tr></table>";
HTMLDocument *doc = [HTMLDocument documentWithString:html];
NSArray<HTMLElement *> *elements = [doc querySelectorAll:@"td:gt(0)"];
XCTAssertEqual(elements.count, 3);
XCTAssertEqualObjects(elements[0].textContent, @"TD #1");
XCTAssertEqualObjects(elements[1].textContent, @"TD #2");
XCTAssertEqualObjects(elements[2].textContent, @"TD #3");
elements = [doc querySelectorAll:@"td:lt(0)"];
XCTAssertEqual(elements.count, 0);
elements = [doc querySelectorAll:@"td:eq(0)"];
XCTAssertEqual(elements.count, 1);
XCTAssertEqualObjects(elements[0].textContent, @"TD #0");
}
@end
@@ -9,6 +9,7 @@
#import "HTML5LibTreeConstructionTest.h"
#import <XCTest/XCTest.h>
#import "HTMLDOM.h"
#import "HTMLDocumentType.h"
#import "HTMLElement.h"
#import "HTMLText.h"
@@ -289,6 +290,8 @@ NS_INLINE NSArray * parseAttribute(NSString *str)
NSRange range = [str rangeOfString:@"=" options:0];
NSString *key = [str substringToIndex:range.location];
key = [key stringByReplacingOccurrencesOfString:@" " withString:@":"];
NSString *value = [str substringFromIndex:range.location + 2];
value = [value substringToIndex:value.length - 1];
@@ -0,0 +1,43 @@
//
// HTMLKitParserTests.m
// HTMLKit
//
// Created by Iska on 16.07.18.
// Copyright © 2018 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "HTMLDOM.h"
@interface HTMLKitParserIssuesTests : XCTestCase
@end
@implementation HTMLKitParserIssuesTests
#pragma mark - Bug Fixes
- (void)testBugFix_Issue_30 {
NSString *html =
@"<body>"
" <svg id='draw_area' width='600' height='800' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1'>"
" <image id='overlay_img' xlink:href='foo.png' width='600' height='800'/>"
" </svg>"
"</body>";
HTMLDocument* document = [HTMLDocument documentWithString:html];
HTMLElement *svg = [document querySelector:@"#draw_area"];
XCTAssertNil(svg.attributes[@"xlink"]);
XCTAssertEqualObjects(svg.attributes[@"xmlns"], @"http://www.w3.org/2000/svg");
XCTAssertEqualObjects(svg.attributes[@"xmlns:xlink"], @"http://www.w3.org/1999/xlink");
HTMLElement *image = [document querySelector:@"#overlay_img"];
XCTAssertNil(image.attributes[@"xlink"]);
XCTAssertNil(image.attributes[@"href"]);
XCTAssertEqualObjects(image.attributes[@"xlink:href"], @"foo.png");
XCTAssertEqualObjects(image.outerHTML, @"<image id=\"overlay_img\" xlink:href=\"foo.png\" width=\"600\" height=\"800\"></image>");
}
@end
@@ -608,4 +608,19 @@ static HTMLNode * (^ LastDescendant)(HTMLNode *) = ^ HTMLNode * (HTMLNode *node)
XCTAssertTrue([element.elementId isEqualToString:divId]);
}
- (void)testBugFix_Issue_28 {
HTMLDocument *document = self.document;
HTMLNodeIterator *iterator = document.body.nodeIterator;
[iterator nextNode]; // Reference node: <body>
HTMLElement *span = (HTMLElement*)iterator.nextNode; // <span>
NSString *spanTag = @"span";
XCTAssertTrue([span.tagName isEqualToString:spanTag]);
HTMLElement *paragraph = span.nextSiblingElement; // <p>
NSString *paragraphTag = @"p";
XCTAssertTrue([paragraph.tagName isEqualToString:paragraphTag]);
}
@end