├── .gitignore ├── Swift ├── Bridging-Header.h ├── HTMLDocument.swift └── HTMLNode+XPath.swift ├── README.md └── Objective-C ├── Xcode-6 ├── HTMLDocument.m ├── HTMLDocument.h ├── HTMLNode+XPath.m ├── HTMLNode+XPath.h └── HTMLNode.h └── Xcode7+ ├── HTMLDocument.m ├── HTMLDocument.h ├── HTMLNode+XPath.m ├── HTMLNode+XPath.h └── HTMLNode.h /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /Swift/Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Wrapper for HTML parser of libxml2 written in Objective-C and Swift 3 =================================================================== This HTML parser gives access to libxml2 with Objective-C in Mac OS (Leopard and higher) and iOS. **The Swift 3 version requires Xcode 8 and Mac OS 10.9+** An optional category/extension provides XPath support. libxml2 is very fast, for less overhead all recursive tasks are realized with C functions. The naming is similar to NSXMLDocument (which lacks in iOS). Unlike NSXMLDocument HTMLDocument does not inherit from HTMLNode, there is no HTMLElement class and you can't create new documents nor change nodes. All methods returning a value/object without parameter(s) are declared as read-only properties for providing dot syntax. Objective-C: Full (ARC) Automatic Reference Counting support using conditional preprocessor macros (Thanks to John Blanco of Rapture In Venice) Objective-C / Swift classes: ============================ - HTMLDocument - XMLDocument (inherits from HTMLDocument - Objective-C only) - HTMLNode Optional category / extension of HTMLNode for XPath support: ------------------------------------------------------------ - HTMLNode+XPath How to use: =========== - Add the class files and the (optional) category/extension files to your project - Add libxml2.dylib to frameworks (Link Binary With Libraries) - not needed with module auto-load (10.9+, iOS7+) - Add $SDKROOT/usr/include/libxml2 to target -> Build Settings > Header Search Paths - Add -lxml2 to target -> Build Settings -> other linker flags Objective-C ----------- - import HTMLDocument.h and HTMLNode+XPath.h (if needed) header files Swift ----- - add Bridging-Header.h to your project and rename it as [Modulename]-Bridging-Header.h where [Modulename] is the module name in your project (usually the project name) - enter the name of the Bridging header also in target -> Build Settings > Objective-C Bridging Header - or add the `#import` lines to your existing bridging header HTMLDocument ============ Create an HTMLDocument with one of these init methods Objective-C ----------- `- (id)initWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error; // designated initializer` `- (id)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error;` `- (id)initWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error;` For each initializer method there is also a convenience class method `+ (HTMLDocument *)documentWith…` The corresponding initializer methods without the encoding parameter assume UTF-8 encoding. Get the root node (actually the `` node) or the `` node of the document with `@property (readonly) HTMLNode *rootNode` `@property (readonly) HTMLNode *body` Swift ----- `init(data: Data?, encoding: String.Encoding = .utf8) throws` `convenience init(contentsOf url: URL, encoding: String.Encoding = .utf8) throws` `convenience init(string: String, encoding: String.Encoding = .utf8) throws` Get the root node (actually the `` node) or the `` node of the document with `let rootNode: HTMLNode` `var body: HTMLNode?` XMLDocument (Objective-C only): =============================== A simple subclass XMLDocument (inherits from HTMLDocument) is added to parse also documents containing pure XML text. Internally libxml2 uses the same node type xmlNode for both HTML and XML documents anyway. HTMLNode: ========= In HTMLNode search for node(s) only within the first level of children of the current node with the prefix `- (HTMLNode *)child…` `- (NSArray *)children…` or search within the siblings of the current node `- (HTMLNode *)sibling…` `- (NSArray *)siblings…` or perform a deep search within all descendants of the current node `- (HTMLNode *)descendant…` `- (NSArray *)descendants…` the appropriate methods to search with XPath within all descendants are `- (HTMLNode *)node…` `- (NSArray *)nodes…` Generic methods to search for a custom XPath are `- (HTMLNode *)nodeForXPath:(NSString *)query error:(NSError **)error;` `- (NSArray *)nodesForXPath:(NSString *)query error:(NSError **)error;` There are many methods to look for tag and attribute names and values. *All Objective-C methods and properties have corresponding functions and variables in the Swift version* You can obtain the `stringValue` of the current text node or the `textContent` of all descendant text nodes as well as its `integerValue`, `doubleValue` (also with a given `locale identifier`) and `dateValue` for a format string (also with a given `time zone`). By default returning string values are trimmed by whitespace and newline characters. The methods starting with raw return the unfiltered values. Differences between the Objective-C and the Swift version --------------------------------------------------------- In Swift all returned values (`String`, `Int`, `Double`, `Date`) are optionals to support convenient optional chaining. Swift ignores by default all text nodes when using the `children` property and the `for - in [HTMLNode]` loop, to change the behaviour see `children` property and `makeIterator()` method in HTMLNode. © 2011-2017 Stefan Klieme -------------------------------------------------------------------------------- /Swift/HTMLDocument.swift: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLDocument.swift # 4 | # # 5 | # Copyright © 2014-2017 by Stefan Klieme # 6 | # # 7 | # Swift wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.1 - 13. Sep 2017 # 10 | # # 11 | # usage: add libxml2.dylib to frameworks (depends on autoload settings) # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # add Bridging-Header.h to your project and rename it as # 15 | # [Modulename]-Bridging-Header.h # 16 | # where [Modulename] is the module name in your project # 17 | # or copy&paste the #import lines into your bridging header # 18 | # # 19 | ##################################################################################### 20 | # # 21 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 22 | # this software and associated documentation files (the "Software"), to deal # 23 | # in the Software without restriction, including without limitation the rights # 24 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 25 | # of the Software, and to permit persons to whom the Software is furnished to do # 26 | # so, subject to the following conditions: # 27 | # The above copyright notice and this permission notice shall be included in # 28 | # all copies or substantial portions of the Software. # 29 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 30 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 31 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 32 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # 33 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 34 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 35 | # # 36 | ###################################################################################*/ 37 | 38 | import Foundation 39 | 40 | enum HTMLDocumentError: Error { 41 | case invalidData 42 | case dataEmpty 43 | case notHTML 44 | case couldNotParse 45 | case missingRootElement 46 | } 47 | 48 | class HTMLDocument { 49 | 50 | /// The class name. 51 | 52 | var className : String { 53 | return "HTMLDocument" 54 | } 55 | 56 | /// The document pointer. 57 | 58 | let htmlDoc: htmlDocPtr 59 | 60 | /// The root node. 61 | 62 | let rootNode: HTMLNode 63 | 64 | /// The head node. 65 | 66 | var head: HTMLNode? { 67 | return rootNode.child(ofTag:"head") 68 | } 69 | 70 | /// The body node. 71 | 72 | var body: HTMLNode? { 73 | return rootNode.child(ofTag:"body") 74 | } 75 | 76 | /// The value of the title tag in the head node. 77 | 78 | var title: String? { 79 | return head?.child(ofTag:"title")?.stringValue 80 | } 81 | 82 | // MARK: - Initialzers 83 | 84 | // default text encoding is UTF-8 85 | 86 | /// Initializes and returns an HTMLDocument object created from an Data object with specified string encoding. 87 | /// - Parameters: 88 | /// - data: A data object with HTML content. 89 | /// - encoding: The string encoding for the HTML content (optional, default is UTF8). 90 | /// - Returns: An initialized HTMLDocument object, if initialization fails an error is thrown. 91 | 92 | init(data: Data?, encoding: String.Encoding = .utf8) throws // designated initializer 93 | { 94 | guard let htmlData = data else { throw HTMLDocumentError.invalidData } 95 | guard !htmlData.isEmpty else { throw HTMLDocumentError.dataEmpty } 96 | 97 | let cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding.rawValue) 98 | let cfEncodingAsString = CFStringConvertEncodingToIANACharSetName(cfEncoding) 99 | let cEncoding = CFStringGetCStringPtr(cfEncodingAsString, 0) 100 | 101 | let htmlParseOptions : CInt = 1 << 0 | 1 << 5 | 1 << 6 // HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING 102 | let cCharacters = htmlData.withUnsafeBytes { (bytes: UnsafePointer) -> [CChar] in 103 | let buffer = UnsafeBufferPointer(start: bytes, count: htmlData.count) 104 | return [CChar](buffer) 105 | } 106 | 107 | guard let htmlDoc = htmlReadMemory(cCharacters, CInt(htmlData.count), nil, cEncoding, htmlParseOptions) else { throw HTMLDocumentError.couldNotParse } 108 | guard let xmlDocRootNode = xmlDocGetRootElement(htmlDoc) else { throw HTMLDocumentError.missingRootElement } 109 | if let docRootNodeName = String.decodeCString(xmlDocRootNode.pointee.name, as: UTF8.self, repairingInvalidCodeUnits: false)?.result, 110 | docRootNodeName == "html" { 111 | self.htmlDoc = htmlDoc 112 | self.rootNode = HTMLNode(pointer: xmlDocRootNode)! 113 | } else { 114 | throw HTMLDocumentError.notHTML 115 | } 116 | } 117 | 118 | /// Initializes and returns an HTMLDocument object created from the HTML contents of a URL-referenced source with specified string encoding. 119 | /// - Parameters: 120 | /// - url: An URL object specifying a URL source. 121 | /// - encoding: The string encoding for the HTML content (optional, default is UTF8). 122 | /// - Returns: An initialized HTMLDocument object, or an error is thrown. 123 | 124 | convenience init(contentsOf url: URL, encoding: String.Encoding = .utf8) throws 125 | { 126 | let data = try Data(contentsOf: url) 127 | try self.init(data:data, encoding:encoding) 128 | } 129 | 130 | /// Initializes and returns an HTMLDocument object created from a string containing HTML markup text with specified string encoding. 131 | /// - Parameters: 132 | /// - string: An string conaining the HTML source. 133 | /// - encoding: The string encoding for the HTML content (optional, default is UTF8). 134 | /// - Returns: An initialized HTMLDocument object, or an error is thrown. 135 | 136 | 137 | convenience init(string: String, encoding: String.Encoding = .utf8) throws 138 | { 139 | try self.init(data: string.data(using: encoding), encoding:encoding) 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Objective-C/Xcode-6/HTMLDocument.m: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLDocument.m # 4 | # # 5 | # Copyright © 2014 by Stefan Klieme # 6 | # # 7 | # Objective-C wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.7 - 20. Sep 2014 # 10 | # # 11 | # usage: add libxml2.dylib to frameworks # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # # 15 | # # 16 | #################################################################################### 17 | # # 18 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 19 | # this software and associated documentation files (the "Software"), to deal # 20 | # in the Software without restriction, including without limitation the rights # 21 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 22 | # of the Software, and to permit persons to whom the Software is furnished to do # 23 | # so, subject to the following conditions: # 24 | # The above copyright notice and this permission notice shall be included in # 25 | # all copies or substantial portions of the Software. # 26 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 27 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 28 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 29 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,# 30 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 31 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 32 | # # 33 | ##################################################################################*/ 34 | 35 | #import "HTMLDocument.h" 36 | 37 | const char *convertStringEncoding(NSStringEncoding encoding, char * buffer, size_t bufferSize); 38 | 39 | const char * convertStringEncoding(NSStringEncoding encoding, char * buffer, size_t bufferSize) { 40 | CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding); 41 | CFStringRef cfEncodingAsString = CFStringConvertEncodingToIANACharSetName(cfEncoding); 42 | const char * cEncoding = CFStringGetCStringPtr(cfEncodingAsString, kCFStringEncodingMacRoman); 43 | if (! cEncoding) { 44 | Boolean ok = CFStringGetCString(cfEncodingAsString, buffer, bufferSize, kCFStringEncodingMacRoman); 45 | NSCAssert(ok, @"convertStringEncoding buffer too small"); 46 | cEncoding = buffer; 47 | } 48 | return cEncoding; 49 | } 50 | 51 | 52 | 53 | @implementation HTMLDocument 54 | @synthesize rootNode; 55 | 56 | #pragma mark - error handling 57 | 58 | - (NSError *)errorForCode:(NSInteger )errorCode 59 | { 60 | NSString *errorString = @""; 61 | switch (errorCode) { 62 | case 1: 63 | errorString = @"No valid data"; 64 | break; 65 | 66 | case 2: 67 | errorString = @"XML data could not be parsed"; 68 | break; 69 | 70 | case 3: 71 | errorString = @"XML data seems not to be of type HTML"; 72 | break; 73 | } 74 | return [NSError errorWithDomain:[@"com.klieme." stringByAppendingString: NSStringFromClass([self class])] 75 | code:errorCode 76 | userInfo:@{NSLocalizedDescriptionKey: errorString}]; 77 | } 78 | 79 | #pragma mark - class methods 80 | 81 | // convenience initializer methods 82 | 83 | + (HTMLDocument *)documentWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 84 | { 85 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithData:data encoding:encoding error:error]); 86 | } 87 | 88 | + (HTMLDocument *)documentWithData:(NSData *)data error:(NSError **)error 89 | { 90 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithData:data error:error]); 91 | } 92 | 93 | + (HTMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error 94 | { 95 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithContentsOfURL:url encoding:encoding error:error]); 96 | } 97 | 98 | + (HTMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error 99 | { 100 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithContentsOfURL:url error:error]); 101 | } 102 | 103 | + (HTMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error 104 | { 105 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithHTMLString:string encoding:encoding error:error]); 106 | } 107 | 108 | + (HTMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error 109 | { 110 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithHTMLString:string error:error]); 111 | } 112 | 113 | #pragma mark - instance init methods 114 | 115 | // designated initializer 116 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 117 | { 118 | self = [super init]; 119 | if (self) { 120 | NSInteger errorCode = 0; 121 | if (data && [data length]) { 122 | int htmlParseOptions = HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING; 123 | char encodingBuffer[32]; 124 | htmlDoc_ = htmlReadMemory([data bytes], (int)[data length], NULL, convertStringEncoding(encoding, encodingBuffer, sizeof(encodingBuffer)), htmlParseOptions); 125 | if (htmlDoc_) { 126 | xmlNodePtr xmlDocRootNode = xmlDocGetRootElement(htmlDoc_); 127 | if (xmlDocRootNode && xmlStrEqual(xmlDocRootNode->name, BAD_CAST "html")) { 128 | rootNode = [[HTMLNode alloc] initWithXMLNode:xmlDocRootNode]; 129 | } 130 | else 131 | errorCode = 3; 132 | } 133 | else 134 | errorCode = 2; 135 | } 136 | else 137 | errorCode = 1; 138 | 139 | if (errorCode) { 140 | if (error) 141 | *error = [self errorForCode:errorCode]; 142 | 143 | SAFE_ARC_RELEASE(self); 144 | return nil; 145 | } 146 | } 147 | return self; 148 | } 149 | 150 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data error:(NSError **)error 151 | { 152 | return [self initWithData:data encoding:NSUTF8StringEncoding error:error]; 153 | } 154 | 155 | - (INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error 156 | { 157 | 158 | NSData *data = [NSData dataWithContentsOfURL:url options:0 error:error]; 159 | if (data && *error == nil) { 160 | return [self initWithData:data encoding:encoding error:error]; 161 | } 162 | return nil; 163 | } 164 | 165 | - (INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url error:(NSError **)error 166 | { 167 | return [self initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:error]; 168 | } 169 | 170 | - (INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error 171 | { 172 | return [self initWithData:[string dataUsingEncoding:encoding] 173 | encoding:encoding 174 | error:error]; 175 | } 176 | 177 | - (INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string error:(NSError **)error 178 | { 179 | return [self initWithHTMLString:string encoding:NSUTF8StringEncoding error:error]; 180 | } 181 | 182 | 183 | - (void)dealloc 184 | { 185 | SAFE_ARC_RELEASE(rootNode); 186 | xmlFreeDoc(htmlDoc_); 187 | SAFE_ARC_SUPER_DEALLOC(); 188 | } 189 | 190 | #pragma mark - frequently used nodes 191 | 192 | - (HTMLNode *)head 193 | { 194 | return [self.rootNode childOfTag:@"head"]; 195 | } 196 | 197 | - (HTMLNode *)body 198 | { 199 | return [self.rootNode childOfTag:@"body"]; 200 | } 201 | 202 | - (NSString *)title 203 | { 204 | return [[self.head childOfTag:@"title"] stringValue]; 205 | } 206 | 207 | 208 | @end 209 | 210 | 211 | @implementation XMLDocument 212 | 213 | + (XMLDocument *)documentWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 214 | { 215 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithData:data encoding:encoding error:error]); 216 | } 217 | 218 | + (XMLDocument *)documentWithData:(NSData *)data error:(NSError **)error 219 | { 220 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithData:data error:error]); 221 | } 222 | 223 | + (XMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error 224 | { 225 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithContentsOfURL:url encoding:encoding error:error]); 226 | } 227 | 228 | + (XMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error 229 | { 230 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithContentsOfURL:url error:error]); 231 | } 232 | 233 | + (XMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error 234 | { 235 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithHTMLString:string encoding:encoding error:error]); 236 | } 237 | 238 | + (XMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error 239 | { 240 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithHTMLString:string error:error]); 241 | } 242 | 243 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 244 | { 245 | self = [super init]; 246 | if (self) { 247 | NSInteger errorCode = 0; 248 | if (data && [data length]) { 249 | int xmlParseOptions = XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING; 250 | char encodingBuffer[32]; 251 | xmlDoc_ = xmlReadMemory([data bytes], (int)[data length], NULL, convertStringEncoding(encoding, encodingBuffer, sizeof(encodingBuffer)), xmlParseOptions); 252 | if (xmlDoc_) { 253 | xmlNodePtr xmlDocRootNode = xmlDocGetRootElement(xmlDoc_); 254 | if (xmlDocRootNode) { 255 | rootNode = [[HTMLNode alloc] initWithXMLNode:xmlDocRootNode]; 256 | } 257 | else 258 | errorCode = 3; 259 | } 260 | else 261 | errorCode = 2; 262 | } 263 | else 264 | errorCode = 1; 265 | 266 | if (errorCode) { 267 | if (error) 268 | *error = [self errorForCode:errorCode]; 269 | 270 | SAFE_ARC_RELEASE(self); 271 | return nil; 272 | } 273 | } 274 | return self; 275 | } 276 | 277 | @end 278 | 279 | 280 | -------------------------------------------------------------------------------- /Objective-C/Xcode7+/HTMLDocument.m: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLDocument.m # 4 | # # 5 | # Copyright © 2014 by Stefan Klieme # 6 | # # 7 | # Objective-C wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.8 - 14. Dez 2015 for Xcode 7+ # 10 | # # 11 | # usage: add libxml2.dylib to frameworks # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # # 15 | # # 16 | #################################################################################### 17 | # # 18 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 19 | # this software and associated documentation files (the "Software"), to deal # 20 | # in the Software without restriction, including without limitation the rights # 21 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 22 | # of the Software, and to permit persons to whom the Software is furnished to do # 23 | # so, subject to the following conditions: # 24 | # The above copyright notice and this permission notice shall be included in # 25 | # all copies or substantial portions of the Software. # 26 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 27 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 28 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 29 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,# 30 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 31 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 32 | # # 33 | ##################################################################################*/ 34 | 35 | #import "HTMLDocument.h" 36 | 37 | const char *convertStringEncoding(NSStringEncoding encoding, char * buffer, size_t bufferSize); 38 | 39 | const char * convertStringEncoding(NSStringEncoding encoding, char * buffer, size_t bufferSize) { 40 | CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding); 41 | CFStringRef cfEncodingAsString = CFStringConvertEncodingToIANACharSetName(cfEncoding); 42 | const char * cEncoding = CFStringGetCStringPtr(cfEncodingAsString, kCFStringEncodingMacRoman); 43 | if (! cEncoding) { 44 | Boolean ok = CFStringGetCString(cfEncodingAsString, buffer, bufferSize, kCFStringEncodingMacRoman); 45 | NSCAssert(ok, @"convertStringEncoding buffer too small"); 46 | cEncoding = buffer; 47 | } 48 | return cEncoding; 49 | } 50 | 51 | 52 | 53 | @implementation HTMLDocument 54 | @synthesize rootNode; 55 | 56 | #pragma mark - error handling 57 | 58 | - (NSError *)errorForCode:(NSInteger )errorCode 59 | { 60 | NSString *errorString = @""; 61 | switch (errorCode) { 62 | case 1: 63 | errorString = @"No valid data"; 64 | break; 65 | 66 | case 2: 67 | errorString = @"XML data could not be parsed"; 68 | break; 69 | 70 | case 3: 71 | errorString = @"XML data seems not to be of type HTML"; 72 | break; 73 | } 74 | return [NSError errorWithDomain:[@"com.klieme." stringByAppendingString: NSStringFromClass([self class])] 75 | code:errorCode 76 | userInfo:@{NSLocalizedDescriptionKey: errorString}]; 77 | } 78 | 79 | #pragma mark - class methods 80 | 81 | // convenience initializer methods 82 | 83 | + (HTMLDocument *)documentWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 84 | { 85 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithData:data encoding:encoding error:error]); 86 | } 87 | 88 | + (HTMLDocument *)documentWithData:(NSData *)data error:(NSError **)error 89 | { 90 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithData:data error:error]); 91 | } 92 | 93 | + (HTMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error 94 | { 95 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithContentsOfURL:url encoding:encoding error:error]); 96 | } 97 | 98 | + (HTMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error 99 | { 100 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithContentsOfURL:url error:error]); 101 | } 102 | 103 | + (HTMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error 104 | { 105 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithHTMLString:string encoding:encoding error:error]); 106 | } 107 | 108 | + (HTMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error 109 | { 110 | return SAFE_ARC_AUTORELEASE([[HTMLDocument alloc] initWithHTMLString:string error:error]); 111 | } 112 | 113 | #pragma mark - instance init methods 114 | 115 | // designated initializer 116 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 117 | { 118 | self = [super init]; 119 | if (self) { 120 | NSInteger errorCode = 0; 121 | if (data && [data length]) { 122 | int htmlParseOptions = HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING; 123 | char encodingBuffer[32]; 124 | htmlDoc_ = htmlReadMemory([data bytes], (int)[data length], NULL, convertStringEncoding(encoding, encodingBuffer, sizeof(encodingBuffer)), htmlParseOptions); 125 | if (htmlDoc_) { 126 | xmlNodePtr xmlDocRootNode = xmlDocGetRootElement(htmlDoc_); 127 | if (xmlDocRootNode && xmlStrEqual(xmlDocRootNode->name, BAD_CAST "html")) { 128 | rootNode = [[HTMLNode alloc] initWithXMLNode:xmlDocRootNode]; 129 | } 130 | else 131 | errorCode = 3; 132 | } 133 | else 134 | errorCode = 2; 135 | } 136 | else 137 | errorCode = 1; 138 | 139 | if (errorCode) { 140 | if (error) 141 | *error = [self errorForCode:errorCode]; 142 | 143 | SAFE_ARC_RELEASE(self); 144 | return nil; 145 | } 146 | } 147 | return self; 148 | } 149 | 150 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data error:(NSError **)error 151 | { 152 | return [self initWithData:data encoding:NSUTF8StringEncoding error:error]; 153 | } 154 | 155 | - (INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error 156 | { 157 | 158 | NSData *data = [NSData dataWithContentsOfURL:url options:0 error:error]; 159 | if (data && *error == nil) { 160 | return [self initWithData:data encoding:encoding error:error]; 161 | } 162 | return nil; 163 | } 164 | 165 | - (INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url error:(NSError **)error 166 | { 167 | return [self initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:error]; 168 | } 169 | 170 | - (INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error 171 | { 172 | return [self initWithData:[string dataUsingEncoding:encoding] 173 | encoding:encoding 174 | error:error]; 175 | } 176 | 177 | - (INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string error:(NSError **)error 178 | { 179 | return [self initWithHTMLString:string encoding:NSUTF8StringEncoding error:error]; 180 | } 181 | 182 | 183 | - (void)dealloc 184 | { 185 | SAFE_ARC_RELEASE(rootNode); 186 | xmlFreeDoc(htmlDoc_); 187 | SAFE_ARC_SUPER_DEALLOC(); 188 | } 189 | 190 | #pragma mark - frequently used nodes 191 | 192 | - (HTMLNode *)head 193 | { 194 | return [self.rootNode childOfTag:@"head"]; 195 | } 196 | 197 | - (HTMLNode *)body 198 | { 199 | return [self.rootNode childOfTag:@"body"]; 200 | } 201 | 202 | - (NSString *)title 203 | { 204 | return [[self.head childOfTag:@"title"] stringValue]; 205 | } 206 | 207 | 208 | @end 209 | 210 | 211 | @implementation XMLDocument 212 | 213 | + (XMLDocument *)documentWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 214 | { 215 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithData:data encoding:encoding error:error]); 216 | } 217 | 218 | + (XMLDocument *)documentWithData:(NSData *)data error:(NSError **)error 219 | { 220 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithData:data error:error]); 221 | } 222 | 223 | + (XMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error 224 | { 225 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithContentsOfURL:url encoding:encoding error:error]); 226 | } 227 | 228 | + (XMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error 229 | { 230 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithContentsOfURL:url error:error]); 231 | } 232 | 233 | + (XMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error 234 | { 235 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithHTMLString:string encoding:encoding error:error]); 236 | } 237 | 238 | + (XMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error 239 | { 240 | return SAFE_ARC_AUTORELEASE([[XMLDocument alloc] initWithHTMLString:string error:error]); 241 | } 242 | 243 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error 244 | { 245 | self = [super init]; 246 | if (self) { 247 | NSInteger errorCode = 0; 248 | if (data && [data length]) { 249 | int xmlParseOptions = XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING; 250 | char encodingBuffer[32]; 251 | xmlDoc_ = xmlReadMemory([data bytes], (int)[data length], NULL, convertStringEncoding(encoding, encodingBuffer, sizeof(encodingBuffer)), xmlParseOptions); 252 | if (xmlDoc_) { 253 | xmlNodePtr xmlDocRootNode = xmlDocGetRootElement(xmlDoc_); 254 | if (xmlDocRootNode) { 255 | rootNode = [[HTMLNode alloc] initWithXMLNode:xmlDocRootNode]; 256 | } 257 | else 258 | errorCode = 3; 259 | } 260 | else 261 | errorCode = 2; 262 | } 263 | else 264 | errorCode = 1; 265 | 266 | if (errorCode) { 267 | if (error) 268 | *error = [self errorForCode:errorCode]; 269 | 270 | SAFE_ARC_RELEASE(self); 271 | return nil; 272 | } 273 | } 274 | return self; 275 | } 276 | 277 | @end 278 | 279 | 280 | -------------------------------------------------------------------------------- /Objective-C/Xcode-6/HTMLDocument.h: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLDocument.h # 4 | # # 5 | # Copyright © 2014 by Stefan Klieme # 6 | # # 7 | # Objective-C wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.7 - 20. Sep 2014 # 10 | # # 11 | # usage: add libxml2.dylib to frameworks # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # # 15 | # # 16 | #################################################################################### 17 | # # 18 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 19 | # this software and associated documentation files (the "Software"), to deal # 20 | # in the Software without restriction, including without limitation the rights # 21 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 22 | # of the Software, and to permit persons to whom the Software is furnished to do # 23 | # so, subject to the following conditions: # 24 | # The above copyright notice and this permission notice shall be included in # 25 | # all copies or substantial portions of the Software. # 26 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 27 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 28 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 29 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,# 30 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 31 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 32 | # # 33 | ##################################################################################*/ 34 | 35 | #import 36 | #import 37 | #import "HTMLNode.h" 38 | 39 | @interface HTMLDocument : NSObject 40 | { 41 | htmlDocPtr htmlDoc_; 42 | HTMLNode *rootNode; 43 | } 44 | 45 | // convenience initializer methods 46 | // default text encoding is UTF-8 47 | 48 | /*! Returns an HTMLDocument object created from an NSData object with specified string encoding 49 | * \param data A data object with HTML content 50 | * \param encoding The string encoding for the HTML content 51 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 52 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 53 | */ 54 | + (HTMLDocument *)documentWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error; 55 | 56 | /*! Returns an HTMLDocument object created from an NSData object with assumed UTF-8 string encoding 57 | * \param data A data object with HTML content 58 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 59 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 60 | */ 61 | + (HTMLDocument *)documentWithData:(NSData *)data error:(NSError **)error; 62 | 63 | /*! Returns an HTMLDocument object created from the HTML contents of a URL-referenced source with specified string encoding 64 | * \param url An NSURL object specifying a URL source 65 | * \param encoding The string encoding for the HTML content 66 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 67 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 68 | */ 69 | + (HTMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error; 70 | 71 | /*! Returns an HTMLDocument object created from the HTML contents of a URL-referenced source with assumed UTF-8 string encoding 72 | * \param url An NSURL object specifying a URL source 73 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 74 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 75 | */ 76 | + (HTMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error; 77 | 78 | /*! Returns an HTMLDocument object created from a string containing HTML markup text with specified string encoding 79 | * \param url An NSURL object specifying a URL source 80 | * \param encoding The string encoding for the HTML content 81 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 82 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 83 | */ 84 | + (HTMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error; 85 | 86 | /*! Returns an HTMLDocument object created from a string containing HTML markup text with assumed UTF-8 string encoding 87 | * \param url An NSURL object specifying a URL source 88 | * \param encoding The string encoding for the HTML content 89 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 90 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 91 | */ 92 | + (HTMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error; 93 | 94 | 95 | /*! Initializes and returns an HTMLDocument object created from an NSData object with specified string encoding 96 | * \param data A data object with HTML or XML content 97 | * \param encoding The string encoding for the HTML or XML content 98 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 99 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 100 | */ 101 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error; // designated initializer 102 | 103 | /*! Initializes and returns an HTMLDocument object created from an NSData object with assumed UTF-8 string encoding 104 | * \param data A data object with HTML or XML content 105 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 106 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 107 | */ 108 | - (INSTANCETYPE_OR_ID)initWithData:(NSData *)data error:(NSError **)error; 109 | 110 | /*! Initializes and returns an HTMLDocument object created from the HTML or XML contents of a URL-referenced source with specified string encoding 111 | * \param url An NSURL object specifying a URL source 112 | * \param encoding The string encoding for the HTML or XML content 113 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 114 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 115 | */ 116 | - (INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error; 117 | 118 | /*! Initializes and returns an HTMLDocument object created from the HTML or XML contents of a URL-referenced source with assumed UTF-8 string encoding 119 | * \param url An NSURL object specifying a URL source 120 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 121 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 122 | */ 123 | - (INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url error:(NSError **)error; 124 | 125 | /*! Initializes and returns an HTMLDocument object created from a string containing HTML or XML markup text with specified string encoding 126 | * \param url An NSURL object specifying a URL source 127 | * \param encoding The string encoding for the HTML or XML content 128 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 129 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 130 | */ 131 | - (INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error; 132 | 133 | /*! Initializes and returns an HTMLDocument object created from a string containing HTML or XML markup text with assumed UTF-8 string encoding 134 | * \param url An NSURL object specifying a URL source 135 | * \param encoding The string encoding for the HTML or XML content 136 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems. 137 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 138 | */ 139 | - (INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string error:(NSError **)error; 140 | 141 | 142 | /*! The root node*/ 143 | @property (readonly) HTMLNode *rootNode; 144 | 145 | /*! The head node*/ 146 | @property (SAFE_ARC_READONLY_OBJ_PROP) HTMLNode *head; 147 | 148 | /*! The body node*/ 149 | @property (SAFE_ARC_READONLY_OBJ_PROP) HTMLNode *body; 150 | 151 | /*! The value of the title tag in the head node*/ 152 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *title; 153 | 154 | @end 155 | 156 | 157 | 158 | @interface XMLDocument : HTMLDocument 159 | { 160 | xmlDocPtr xmlDoc_; 161 | } 162 | 163 | /*! Returns an XMLDocument object created from an NSData object with specified string encoding 164 | * \param data A data object with XML content 165 | * \param encoding The string encoding for the XML content 166 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 167 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 168 | */ 169 | + (XMLDocument *)documentWithData:(NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error; 170 | 171 | /*! Returns an XMLDocument object created from an NSData object with assumed UTF-8 string encoding 172 | * \param data A data object with XML content 173 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 174 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 175 | */ 176 | + (XMLDocument *)documentWithData:(NSData *)data error:(NSError **)error; 177 | 178 | /*! Returns an XMLDocument object created from the XML contents of a URL-referenced source with specified string encoding 179 | * \param url An NSURL object specifying a URL source 180 | * \param encoding The string encoding for the XML content 181 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 182 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 183 | */ 184 | + (XMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error; 185 | 186 | /*! Returns an XMLDocument object created from the XML contents of a URL-referenced source with assumed UTF-8 string encoding 187 | * \param url An NSURL object specifying a URL source 188 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 189 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 190 | */ 191 | + (XMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error; 192 | 193 | /*! Returns an XMLDocument object created from a string containing XML markup text with specified string encoding 194 | * \param url An NSURL object specifying a URL source 195 | * \param encoding The string encoding for the XML content 196 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 197 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 198 | */ 199 | + (XMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error; 200 | 201 | /*! Returns an XMLDocument object created from a string containing XML markup text with assumed UTF-8 string encoding 202 | * \param url An NSURL object specifying a URL source 203 | * \param encoding The string encoding for the XML content 204 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 205 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 206 | */ 207 | + (XMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error; 208 | 209 | 210 | 211 | @end 212 | -------------------------------------------------------------------------------- /Objective-C/Xcode7+/HTMLDocument.h: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLDocument.h # 4 | # # 5 | # Copyright © 2014 by Stefan Klieme # 6 | # # 7 | # Objective-C wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.8 - 14. Dez 2015 for Xcode 7+ # 10 | # # 11 | # usage: add libxml2.dylib to frameworks # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # # 15 | # # 16 | #################################################################################### 17 | # # 18 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 19 | # this software and associated documentation files (the "Software"), to deal # 20 | # in the Software without restriction, including without limitation the rights # 21 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 22 | # of the Software, and to permit persons to whom the Software is furnished to do # 23 | # so, subject to the following conditions: # 24 | # The above copyright notice and this permission notice shall be included in # 25 | # all copies or substantial portions of the Software. # 26 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 27 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 28 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 29 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,# 30 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 31 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 32 | # # 33 | ##################################################################################*/ 34 | 35 | #import 36 | #import 37 | #import "HTMLNode.h" 38 | 39 | @interface HTMLDocument : NSObject 40 | { 41 | htmlDocPtr htmlDoc_; 42 | HTMLNode *rootNode; 43 | } 44 | 45 | NS_ASSUME_NONNULL_BEGIN 46 | 47 | // convenience initializer methods 48 | // default text encoding is UTF-8 49 | 50 | /*! Returns an HTMLDocument object created from an NSData object with specified string encoding 51 | * \param data A data object with HTML content 52 | * \param encoding The string encoding for the HTML content 53 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 54 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 55 | */ 56 | + (nullable HTMLDocument *)documentWithData:(nullable NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error; 57 | 58 | /*! Returns an HTMLDocument object created from an NSData object with assumed UTF-8 string encoding 59 | * \param data A data object with HTML content 60 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 61 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 62 | */ 63 | + (nullable HTMLDocument *)documentWithData:(nullable NSData *)data error:(NSError **)error; 64 | 65 | /*! Returns an HTMLDocument object created from the HTML contents of a URL-referenced source with specified string encoding 66 | * \param url An NSURL object specifying a URL source 67 | * \param encoding The string encoding for the HTML content 68 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 69 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 70 | */ 71 | + (nullable HTMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error; 72 | 73 | /*! Returns an HTMLDocument object created from the HTML contents of a URL-referenced source with assumed UTF-8 string encoding 74 | * \param url An NSURL object specifying a URL source 75 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 76 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 77 | */ 78 | + (nullable HTMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error; 79 | 80 | /*! Returns an HTMLDocument object created from a string containing HTML markup text with specified string encoding 81 | * \param url An NSURL object specifying a URL source 82 | * \param encoding The string encoding for the HTML content 83 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 84 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 85 | */ 86 | + (nullable HTMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error; 87 | 88 | /*! Returns an HTMLDocument object created from a string containing HTML markup text with assumed UTF-8 string encoding 89 | * \param url An NSURL object specifying a URL source 90 | * \param encoding The string encoding for the HTML content 91 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 92 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 93 | */ 94 | + (nullable HTMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error; 95 | 96 | 97 | /*! Initializes and returns an HTMLDocument object created from an NSData object with specified string encoding 98 | * \param data A data object with HTML or XML content 99 | * \param encoding The string encoding for the HTML or XML content 100 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 101 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 102 | */ 103 | - (nullable INSTANCETYPE_OR_ID)initWithData:(nullable NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error; // designated initializer 104 | 105 | /*! Initializes and returns an HTMLDocument object created from an NSData object with assumed UTF-8 string encoding 106 | * \param data A data object with HTML or XML content 107 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 108 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 109 | */ 110 | - (nullable INSTANCETYPE_OR_ID)initWithData:(nullable NSData *)data error:(NSError **)error; 111 | 112 | /*! Initializes and returns an HTMLDocument object created from the HTML or XML contents of a URL-referenced source with specified string encoding 113 | * \param url An NSURL object specifying a URL source 114 | * \param encoding The string encoding for the HTML or XML content 115 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 116 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 117 | */ 118 | - (nullable INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error; 119 | 120 | /*! Initializes and returns an HTMLDocument object created from the HTML or XML contents of a URL-referenced source with assumed UTF-8 string encoding 121 | * \param url An NSURL object specifying a URL source 122 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 123 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 124 | */ 125 | - (nullable INSTANCETYPE_OR_ID)initWithContentsOfURL:(NSURL *)url error:(NSError **)error; 126 | 127 | /*! Initializes and returns an HTMLDocument object created from a string containing HTML or XML markup text with specified string encoding 128 | * \param url An NSURL object specifying a URL source 129 | * \param encoding The string encoding for the HTML or XML content 130 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 131 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 132 | */ 133 | - (nullable INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error; 134 | 135 | /*! Initializes and returns an HTMLDocument object created from a string containing HTML or XML markup text with assumed UTF-8 string encoding 136 | * \param url An NSURL object specifying a URL source 137 | * \param encoding The string encoding for the HTML or XML content 138 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems. 139 | * \returns An initialized HTMLDocument object, or nil if initialization fails because of parsing errors or other reasons 140 | */ 141 | - (nullable INSTANCETYPE_OR_ID)initWithHTMLString:(NSString *)string error:(NSError **)error; 142 | 143 | 144 | /*! The root node*/ 145 | @property (readonly, nullable) HTMLNode *rootNode; 146 | 147 | /*! The head node*/ 148 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) HTMLNode *head; 149 | 150 | /*! The body node*/ 151 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) HTMLNode *body; 152 | 153 | /*! The value of the title tag in the head node*/ 154 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *title; 155 | 156 | 157 | @end 158 | 159 | 160 | 161 | @interface XMLDocument : HTMLDocument 162 | { 163 | xmlDocPtr xmlDoc_; 164 | } 165 | 166 | 167 | /*! Returns an XMLDocument object created from an NSData object with specified string encoding 168 | * \param data A data object with XML content 169 | * \param encoding The string encoding for the XML content 170 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 171 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 172 | */ 173 | + (nullable XMLDocument *)documentWithData:(nullable NSData *)data encoding:(NSStringEncoding )encoding error:(NSError **)error; 174 | 175 | /*! Returns an XMLDocument object created from an NSData object with assumed UTF-8 string encoding 176 | * \param data A data object with XML content 177 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 178 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 179 | */ 180 | + (nullable XMLDocument *)documentWithData:(nullable NSData *)data error:(NSError **)error; 181 | 182 | /*! Returns an XMLDocument object created from the XML contents of a URL-referenced source with specified string encoding 183 | * \param url An NSURL object specifying a URL source 184 | * \param encoding The string encoding for the XML content 185 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 186 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 187 | */ 188 | + (nullable XMLDocument *)documentWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding )encoding error:(NSError **)error; 189 | 190 | /*! Returns an XMLDocument object created from the XML contents of a URL-referenced source with assumed UTF-8 string encoding 191 | * \param url An NSURL object specifying a URL source 192 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 193 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 194 | */ 195 | + (nullable XMLDocument *)documentWithContentsOfURL:(NSURL *)url error:(NSError **)error; 196 | 197 | /*! Returns an XMLDocument object created from a string containing XML markup text with specified string encoding 198 | * \param url An NSURL object specifying a URL source 199 | * \param encoding The string encoding for the XML content 200 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 201 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 202 | */ 203 | + (nullable XMLDocument *)documentWithHTMLString:(NSString *)string encoding:(NSStringEncoding )encoding error:(NSError **)error; 204 | 205 | /*! Returns an XMLDocument object created from a string containing XML markup text with assumed UTF-8 string encoding 206 | * \param url An NSURL object specifying a URL source 207 | * \param encoding The string encoding for the XML content 208 | * \param error An error object that, on return, identifies any parsing errors and warnings or connection problems 209 | * \returns An initialized XMLDocument object, or nil if initialization fails because of parsing errors or other reasons 210 | */ 211 | + (nullable XMLDocument *)documentWithHTMLString:(NSString *)string error:(NSError **)error; 212 | 213 | NS_ASSUME_NONNULL_END 214 | 215 | @end 216 | -------------------------------------------------------------------------------- /Swift/HTMLNode+XPath.swift: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLNode+XPath.swift - Extension for HTMLNode # 4 | # # 5 | # Copyright © 2014-2017 by Stefan Klieme # 6 | # # 7 | # Swift wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.1 - 13. Sep 2017 # 10 | # # 11 | # usage: add libxml2.dylib to frameworks (depends on autoload settings) # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # add Bridging-Header.h to your project and rename it as # 15 | # [Modulename]-Bridging-Header.h # 16 | # where [Modulename] is the module name in your project # 17 | # or copy&paste the #import lines into your bridging header # 18 | # # 19 | ##################################################################################### 20 | # # 21 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 22 | # this software and associated documentation files (the "Software"), to deal # 23 | # in the Software without restriction, including without limitation the rights # 24 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 25 | # of the Software, and to permit persons to whom the Software is furnished to do # 26 | # so, subject to the following conditions: # 27 | # The above copyright notice and this permission notice shall be included in # 28 | # all copies or substantial portions of the Software. # 29 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 30 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 31 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 32 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # 33 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 34 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 35 | # # 36 | ###################################################################################*/ 37 | 38 | import Foundation 39 | 40 | enum XPathError: Error { 41 | case evaluationFailed(Int32, String) 42 | case contextFailed 43 | } 44 | 45 | extension HTMLNode { 46 | 47 | // XPath format predicates 48 | 49 | struct XPathPredicate { 50 | static var node: (String) -> String = { return "./descendant::\($0)" } 51 | static var nodeWith: (String, String) -> String = { return "//\($0)[@\($1)]" } 52 | static var attribute: (String) -> String = { return "//*[@\($0)]" } 53 | static var attributeIsEqual: (String, String) -> String = { return "//*[@\($0) ='\($1)']" } 54 | static var attributeBeginsWith: (String, String) -> String = { return "./*[starts-with(@\($0),'\($1)')]" } 55 | static var attributeEndsWith: (String, String) -> String = { return "//*['\($1)' = substring(@\($0)@, string-length(@\($0))- string-length('\($1)') +1)]" } 56 | static var attributeContains: (String, String) -> String = { return "//*[contains(@\($0),'\($1)')]" } 57 | } 58 | 59 | // performXPathQuery() Returns an array of HTMLNode objects if the query matches any nodes, otherwise an empty array 60 | 61 | private func performXPathQuery(node : xmlNodePtr, query : String, returnSingleNode : Bool) throws -> [HTMLNode] 62 | { 63 | let xmlDoc = node.pointee.doc 64 | let xpathContext = xmlXPathNewContext(xmlDoc) 65 | 66 | guard xpathContext != nil else { throw XPathError.contextFailed } 67 | defer { xmlXPathFreeContext(xpathContext!) } 68 | 69 | let xpathErrorCallBack : xmlStructuredErrorFunc = { (context, errorPtr) in 70 | let node = Unmanaged.fromOpaque(context!).takeUnretainedValue() 71 | let error = errorPtr!.pointee 72 | let message = error.message! 73 | node.xpathErrorCode = error.code 74 | node.xpathErrorMessage = String(validatingUTF8: message)!.trimmingCharacters(in: CharacterSet.newlines) 75 | } 76 | 77 | xmlSetStructuredErrorFunc(UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()), xpathErrorCallBack) 78 | 79 | defer { xmlSetStructuredErrorFunc(nil, nil) } 80 | 81 | let xpathObject = query.withXmlChar { xmlQuery -> xmlXPathObjectPtr? in 82 | if (query.hasPrefix("//") || query.hasPrefix("./")) { 83 | return xmlXPathNodeEval(node, xmlQuery, xpathContext) 84 | } else { 85 | return xmlXPathEvalExpression(xmlQuery, xpathContext) 86 | } 87 | } 88 | 89 | guard xpathObject != nil else { throw XPathError.evaluationFailed(xpathErrorCode, xpathErrorMessage) } 90 | defer { xmlXPathFreeObject(xpathObject) } 91 | 92 | if let nodes = xpathObject!.pointee.nodesetval, nodes.pointee.nodeNr > 0, nodes.pointee.nodeTab != nil { 93 | let nodesArray = UnsafeBufferPointer(start: nodes.pointee.nodeTab, count: Int(nodes.pointee.nodeNr)) 94 | if returnSingleNode { 95 | if let node = HTMLNode(pointer:nodesArray[0]) { 96 | return [node] 97 | } 98 | } else { 99 | return nodesArray.compactMap{ HTMLNode(pointer:$0) } 100 | } 101 | } 102 | return [HTMLNode]() 103 | } 104 | 105 | 106 | // MARK: - Objective-C wrapper for XPath Query function 107 | 108 | /// Returns the first descendant node for a XPath query. 109 | /// - Parameters: 110 | /// - query: The XPath query string. 111 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 112 | 113 | func node(forXPath query : String) throws -> HTMLNode? 114 | { 115 | return try performXPathQuery(node: pointer, query: query, returnSingleNode: true).first 116 | } 117 | 118 | /// Returns all descendant nodes for a XPath query. 119 | /// - Parameters: 120 | /// - query: The XPath query string. 121 | /// - Returns: The array of all found descendant nodes or an empty array. 122 | 123 | func nodes(forXPath query : String) throws -> [HTMLNode] 124 | { 125 | return try performXPathQuery(node: pointer, query: query, returnSingleNode: false) 126 | } 127 | 128 | // MARK: - specific XPath Query methods 129 | // Note: In the HTMLNode main class all appropriate query methods begin with descendant instead of node 130 | 131 | /// Returns the first descendant node for a matching tag name and matching attribute name. 132 | /// - Parameters: 133 | /// - tag: The tag name. 134 | /// - attribute: The attribute name (optional, default is no attribute). 135 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 136 | 137 | func node(ofTag tag : String, with attribute : String = "") throws -> HTMLNode? 138 | { 139 | let predicate = attribute.isEmpty ? XPathPredicate.node(tag) : XPathPredicate.nodeWith(tag, attribute) 140 | return try node(forXPath: predicate) 141 | } 142 | 143 | /// Returns all descendant nodes for a matching tag name and matching attribute name. 144 | /// - Parameters: 145 | /// - tag: The tag name. 146 | /// - attribute: The attribute name (optional, default is no attribute). 147 | /// - Returns: The array of all found descendant nodes or an empty array. 148 | 149 | func nodes(ofTag tag : String, with attribute : String = "") throws -> [HTMLNode] 150 | { 151 | let predicate = attribute.isEmpty ? XPathPredicate.node(tag) : XPathPredicate.nodeWith(tag, attribute) 152 | return try nodes(forXPath: predicate) 153 | } 154 | 155 | /// Returns the first descendant node for a specified attribute name. 156 | /// - Parameters: 157 | /// - attribute: The attribute name. 158 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 159 | 160 | func node(withAttribute attribute : String) throws -> HTMLNode? 161 | { 162 | return try node(forXPath: XPathPredicate.attribute(attribute)) 163 | } 164 | 165 | /// Returns all descendant nodes for a specified attribute name. 166 | /// - Parameters: 167 | /// - attribute: The attribute name. 168 | /// - Returns: The array of all found descendant nodes or an empty array. 169 | 170 | func nodes(withAttribute attribute : String) throws -> [HTMLNode] 171 | { 172 | return try nodes(forXPath: XPathPredicate.attribute(attribute)) 173 | } 174 | 175 | /// Returns the first descendant node for a matching attribute name and matching attribute value. 176 | /// - Parameters: 177 | /// - attribute: The attribute name. 178 | /// - value: The attribute value. 179 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 180 | 181 | func node(withAttribute attribute : String, matches value : String) throws -> HTMLNode? 182 | { 183 | return try node(forXPath: XPathPredicate.attributeIsEqual(attribute, value)) 184 | } 185 | 186 | /// Returns all descendant nodes for a matching attribute name and matching attribute value. 187 | /// - Parameters: 188 | /// - attribute: The attribute name. 189 | /// - value: The attribute value. 190 | /// - Returns: The array of all found descendant nodes or an empty array. 191 | 192 | func nodes(withAttribute attribute : String, matches value : String) throws -> [HTMLNode] 193 | { 194 | return try nodes(forXPath: XPathPredicate.attributeIsEqual(attribute, value)) 195 | } 196 | 197 | /// Returns the first descendant node for a matching attribute name and beginning of the attribute value. 198 | /// - Parameters: 199 | /// - attribute: The attribute name. 200 | /// - value: The attribute value. 201 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 202 | 203 | func node(withAttribute attribute : String, beginsWith value : String) throws -> HTMLNode? 204 | { 205 | return try node(forXPath: XPathPredicate.attributeBeginsWith(attribute, value)) 206 | } 207 | 208 | /// Returns all descendant nodes for a matching attribute name and beginning of the attribute value. 209 | /// - Parameters: 210 | /// - attribute: The attribute name. 211 | /// - value: The attribute value. 212 | /// - Returns: The array of all found descendant nodes or an empty array. 213 | 214 | func nodes(withAttribute attribute : String, beginsWith value : String) throws -> [HTMLNode] 215 | { 216 | return try nodes(forXPath: XPathPredicate.attributeBeginsWith(attribute, value)) 217 | } 218 | 219 | /// Returns the first descendant node for a matching attribute name and ending of the attribute value. 220 | /// - Parameters: 221 | /// - attribute: The attribute name. 222 | /// - value: The attribute value. 223 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 224 | 225 | func node(withAttribute attribute : String, endsWith value : String) throws -> HTMLNode? 226 | { 227 | return try node(forXPath: XPathPredicate.attributeEndsWith(attribute, value)) 228 | } 229 | 230 | /// Returns all descendant nodes for a matching attribute name and ending of the attribute value. 231 | /// - Parameters: 232 | /// - attribute: The attribute name. 233 | /// - value: The attribute value. 234 | /// - Returns: The array of all found descendant nodes or an empty array. 235 | 236 | func nodes(withAttribute attribute : String, endsWith value : String) throws -> [HTMLNode] 237 | { 238 | return try nodes(forXPath: XPathPredicate.attributeEndsWith(attribute, value)) 239 | } 240 | 241 | /// Returns the first descendant node for a matching attribute name and containing the attribute value. 242 | /// - Parameters: 243 | /// - attribute: The attribute name. 244 | /// - value: The attribute value. 245 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 246 | 247 | func node(withAttribute attribute : String, contains value : String) throws -> HTMLNode? 248 | { 249 | return try node(forXPath: XPathPredicate.attributeContains(attribute, value)) 250 | } 251 | 252 | /// Returns all descendant nodes for a matching attribute name and containing the attribute value. 253 | /// - Parameters: 254 | /// - attribute: The attribute name. 255 | /// - value: The attribute value. 256 | /// - Returns: The array of all found descendant nodes or an empty array. 257 | 258 | func nodes(withAttribute attribute : String, contains value : String) throws -> [HTMLNode] 259 | { 260 | return try nodes(forXPath: XPathPredicate.attributeContains(attribute, value)) 261 | } 262 | 263 | /// Returns the first descendant node for a specified class name. 264 | /// - Parameters: 265 | /// - value The class name. 266 | /// - Returns: The first found descendant node or nil if no node matches the parameters. 267 | 268 | func node(withClass value : String) throws -> HTMLNode? 269 | { 270 | return try node(withAttribute: AttributeKey.`class`, matches: value) 271 | } 272 | 273 | /// Returns all descendant nodes for a specified class name. 274 | /// - Parameters: 275 | /// - value The class name. 276 | /// - Returns: The array of all found descendant nodes or an empty array. 277 | 278 | func nodes(withClass value : String) throws -> [HTMLNode] 279 | { 280 | return try nodes(withAttribute: AttributeKey.`class`, matches: value) 281 | } 282 | 283 | } 284 | -------------------------------------------------------------------------------- /Objective-C/Xcode-6/HTMLNode+XPath.m: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLNode+XPath.m # 4 | # Category of HTMLNode for XPath support # 5 | # # 6 | # Copyright © 2014 by Stefan Klieme # 7 | # # 8 | # Objective-C wrapper for HTML parser of libxml2 # 9 | # # 10 | # Version 1.7 - 20. Sep 2014 # 11 | # # 12 | # usage: add #import HTMLNode+XPath.h # 13 | # # 14 | # # 15 | ##################################################################################### 16 | # # 17 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 18 | # this software and associated documentation files (the "Software"), to deal # 19 | # in the Software without restriction, including without limitation the rights # 20 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 21 | # of the Software, and to permit persons to whom the Software is furnished to do # 22 | # so, subject to the following conditions: # 23 | # The above copyright notice and this permission notice shall be included in # 24 | # all copies or substantial portions of the Software. # 25 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 26 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 27 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 28 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # 29 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 30 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 31 | # # 32 | ###################################################################################*/ 33 | 34 | 35 | #import "HTMLNode+XPath.h" 36 | #import 37 | #import 38 | 39 | static NSString *kXPathPredicateNode = @"/descendant::%@"; 40 | static NSString *kXPathPredicateNodeWithAttribute = @"//%@[@%@]"; 41 | static NSString *kXPathPredicateAttribute = @"//*[@%@]"; 42 | static NSString *kXPathPredicateAttributeIsEqual = @"//*[@%@ ='%@']"; 43 | static NSString *kXPathPredicateAttributeBeginsWith = @"//*[starts-with(@%@,'%@')]"; 44 | static NSString *kXPathPredicateAttributeEndsWith = @"//*['%@' = substring(@%@, string-length(@%@)- string-length('%@') +1)]"; 45 | static NSString *kXPathPredicateAttributeContains = @"//*[contains(@%@,'%@')]"; 46 | 47 | static id performXPathQuery(xmlNode * node, NSString * query, BOOL returnSingleNode, BOOL considerError, HTMLNode *htmlNode); 48 | static void XPathErrorCallback(void *node, xmlErrorPtr err); 49 | 50 | #pragma mark - static C functions 51 | 52 | // xpath error callback 53 | static void XPathErrorCallback(void *node, xmlErrorPtr err) 54 | { 55 | NSInteger errorCode = (NSInteger )err->code; 56 | if ((errorCode > 1199) && (errorCode < 1223)) { // filter XPath errors 1200 - 1222 57 | char *errMessage = err->message; 58 | NSString *errorMessage = (errMessage) ? [NSString stringWithUTF8String:errMessage] : @"unknown error"; 59 | #if __has_feature(objc_arc) 60 | [(__bridge_transfer HTMLNode *)node setErrorWithMessage:errorMessage andCode:errorCode]; 61 | #else 62 | [(HTMLNode *)node setErrorWithMessage:errorMessage andCode:errorCode]; 63 | #endif 64 | } 65 | } 66 | 67 | 68 | // performXPathQuery() returns one HTMLNode object or an array of HTMLNode objects 69 | // if the query matches any nodes, otherwise nil. 70 | 71 | static id performXPathQuery(xmlNode * node, NSString * query, BOOL returnSingleNode, BOOL considerError, HTMLNode *htmlNode) 72 | { 73 | if (query == nil) { 74 | if (considerError) [htmlNode setErrorWithMessage:@"query string must not be nil value" andCode:6]; 75 | return nil; 76 | } 77 | xmlXPathContextPtr xpathContext; 78 | xmlXPathObjectPtr xpathObject; 79 | id result = (returnSingleNode) ? nil : [NSMutableArray array]; 80 | 81 | xpathContext = xmlXPathNewContext((xmlDocPtr)node); 82 | if (xpathContext) { 83 | if (considerError) 84 | #if __has_feature(objc_arc) 85 | { xmlSetStructuredErrorFunc((__bridge_retained void *)htmlNode, XPathErrorCallback); } 86 | #else 87 | { xmlSetStructuredErrorFunc((void *)htmlNode, XPathErrorCallback); } 88 | #endif 89 | 90 | xpathObject = xmlXPathEvalExpression((xmlChar *)[query UTF8String], xpathContext); 91 | 92 | if (xpathObject) { 93 | xmlNodeSetPtr nodes = xpathObject->nodesetval; 94 | if (xmlXPathNodeSetIsEmpty(nodes) == NO) { 95 | if (returnSingleNode) { 96 | result = [HTMLNode nodeWithXMLNode:nodes->nodeTab[0]]; 97 | } else { 98 | 99 | 100 | for (int i = 0; i < nodes->nodeNr; i++) { 101 | HTMLNode *matchedNode = [[HTMLNode alloc] initWithXMLNode:nodes->nodeTab[i]]; 102 | [result addObject:matchedNode]; 103 | #if !__has_feature(objc_arc) 104 | [matchedNode release]; 105 | #endif 106 | } 107 | } 108 | } 109 | xmlXPathFreeObject(xpathObject); 110 | } 111 | else { 112 | if (considerError) [htmlNode setErrorWithMessage:@"Could not evaluate XPath expression" andCode:5]; 113 | } 114 | xmlXPathFreeContext(xpathContext); 115 | } 116 | else 117 | if (considerError) [htmlNode setErrorWithMessage:@"Could not create XPath context" andCode:4]; 118 | 119 | return result; 120 | } 121 | 122 | #pragma mark 123 | 124 | @implementation HTMLNode (XPath) 125 | 126 | #pragma mark - private getter 127 | 128 | - (xmlNode *)xmlNode 129 | { 130 | return xmlNode_; 131 | } 132 | 133 | #pragma mark - Objective-C wrapper for XPath Query function 134 | 135 | // perform XPath query and return first search result 136 | 137 | - (HTMLNode *)nodeForXPath:(NSString *)query error:(NSError **)error 138 | { 139 | self.xpathError = nil; 140 | HTMLNode *result = (HTMLNode *)performXPathQuery(xmlNode_, query, YES, error != nil, self); 141 | if (error) *error = xpathError; 142 | return result; 143 | } 144 | 145 | - (HTMLNode *)nodeForXPath:(NSString *)query 146 | { 147 | return [self nodeForXPath:query error:nil]; 148 | } 149 | 150 | 151 | // perform XPath query and return all results 152 | 153 | - (NSArray *)nodesForXPath:(NSString *)query error:(NSError **)error 154 | { 155 | self.xpathError = nil; 156 | NSArray *result = (NSArray *)performXPathQuery(xmlNode_, query, NO, error != nil, self); 157 | if (error) *error = xpathError; 158 | return result; 159 | } 160 | 161 | - (NSArray *)nodesForXPath:(NSString *)query 162 | { 163 | return [self nodesForXPath:query error:nil]; 164 | } 165 | 166 | #pragma mark - specific XPath Query methods 167 | 168 | - (HTMLNode *)nodeOfTag:(NSString *)tagName error:(NSError **)error 169 | { 170 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateNode, tagName] error:error]; 171 | } 172 | 173 | - (HTMLNode *)nodeOfTag:(NSString *)tagName 174 | { 175 | return [self nodeOfTag:tagName error:nil]; 176 | } 177 | 178 | - (NSArray *)nodesOfTag:(NSString *)tagName error:(NSError **)error 179 | { 180 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateNode, tagName] error:error]; 181 | } 182 | 183 | - (NSArray *)nodesOfTag:(NSString *)tagName 184 | { 185 | return [self nodesOfTag:tagName error:nil]; 186 | } 187 | 188 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName error:(NSError **)error 189 | { 190 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttribute, attributeName] error:error]; 191 | } 192 | 193 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName 194 | { 195 | return [self nodeWithAttribute:attributeName error:nil]; 196 | } 197 | 198 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName error:(NSError **)error 199 | { 200 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttribute, attributeName] error:error]; 201 | } 202 | 203 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName 204 | { 205 | return [self nodesWithAttribute:attributeName error:nil]; 206 | } 207 | 208 | - (HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error 209 | { 210 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateNodeWithAttribute, tagName, attributeName] error:error]; 211 | } 212 | 213 | - (HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName 214 | { 215 | return [self nodeOfTag:tagName withAttribute:attributeName error:nil]; 216 | } 217 | 218 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error 219 | { 220 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateNodeWithAttribute, tagName, attributeName] error:error]; 221 | } 222 | 223 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName 224 | { 225 | return [self nodesOfTag:tagName withAttribute:attributeName error:nil]; 226 | } 227 | 228 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error 229 | { 230 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeIsEqual, attributeName, value] error:error]; 231 | } 232 | 233 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value 234 | { 235 | return [self nodeWithAttribute:attributeName valueMatches:value error:nil]; 236 | } 237 | 238 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error 239 | { 240 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeIsEqual, attributeName, value] error:error]; 241 | } 242 | 243 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value 244 | { 245 | return [self nodesWithAttribute:attributeName valueMatches:value error:nil]; 246 | } 247 | 248 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error 249 | { 250 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeBeginsWith, attributeName, value] error:error]; 251 | } 252 | 253 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value 254 | { 255 | return [self nodeWithAttribute:attributeName valueBeginsWith:value error:nil]; 256 | } 257 | 258 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error 259 | { 260 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeBeginsWith, attributeName, value] error:error]; 261 | } 262 | 263 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value 264 | { 265 | return [self nodesWithAttribute:attributeName valueBeginsWith:value error:nil]; 266 | } 267 | 268 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error 269 | { 270 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeEndsWith, value, attributeName, attributeName, value] error:error]; 271 | } 272 | 273 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value 274 | { 275 | return [self nodeWithAttribute:attributeName valueEndsWith:value error:nil]; 276 | } 277 | 278 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error 279 | { 280 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeEndsWith, value, attributeName, attributeName, value] error:error]; 281 | } 282 | 283 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value 284 | { 285 | return [self nodesWithAttribute:attributeName valueEndsWith:value error:nil]; 286 | } 287 | 288 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error 289 | { 290 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeContains, attributeName, value] error:error]; 291 | } 292 | 293 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value 294 | { 295 | return [self nodeWithAttribute:attributeName valueContains:value error:nil]; 296 | } 297 | 298 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error 299 | { 300 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeContains, attributeName, value] error:error]; 301 | } 302 | 303 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value 304 | { 305 | return [self nodesWithAttribute:attributeName valueContains:value error:nil]; 306 | } 307 | 308 | - (HTMLNode *)nodeWithClass:(NSString *)classValue error:(NSError **)error 309 | { 310 | return [self nodeWithAttribute:kClassKey valueMatches:classValue error:error]; 311 | } 312 | 313 | - (HTMLNode *)nodeWithClass:(NSString *)classValue 314 | { 315 | return [self nodeWithAttribute:kClassKey valueMatches:classValue]; 316 | } 317 | 318 | - (NSArray *)nodesWithClass:(NSString *)classValue error:(NSError **)error 319 | { 320 | return [self nodesWithAttribute:kClassKey valueMatches:classValue error:error]; 321 | } 322 | 323 | - (NSArray *)nodesWithClass:(NSString *)classValue 324 | { 325 | return [self nodesWithAttribute:kClassKey valueMatches:classValue]; 326 | } 327 | 328 | #pragma mark - Overriding Equality 329 | 330 | //compare HTMLNode objects with XPath 331 | - (BOOL)isEqual:(HTMLNode *)node 332 | { 333 | if (node == self) return YES; 334 | if (!node || ![node isKindOfClass: [self class]]) return NO; 335 | return xmlXPathCmpNodes([self xmlNode], [node xmlNode]) == 0; 336 | } 337 | 338 | #pragma mark - error handling 339 | 340 | - (void)setErrorWithMessage:(NSString *)message andCode:(NSInteger)code 341 | { 342 | self.xpathError = [NSError errorWithDomain:@"com.klieme.HTMLDocument" 343 | code:code 344 | userInfo:@{NSLocalizedDescriptionKey: message}]; 345 | } 346 | 347 | @end 348 | -------------------------------------------------------------------------------- /Objective-C/Xcode7+/HTMLNode+XPath.m: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLNode+XPath.m # 4 | # Category of HTMLNode for XPath support # 5 | # # 6 | # Copyright © 2014 by Stefan Klieme # 7 | # # 8 | # Objective-C wrapper for HTML parser of libxml2 # 9 | # # 10 | # Version 1.8 - 14. Dez 2015 for Xcode 7+ # 11 | # # 12 | # usage: add #import HTMLNode+XPath.h # 13 | # # 14 | # # 15 | ##################################################################################### 16 | # # 17 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 18 | # this software and associated documentation files (the "Software"), to deal # 19 | # in the Software without restriction, including without limitation the rights # 20 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 21 | # of the Software, and to permit persons to whom the Software is furnished to do # 22 | # so, subject to the following conditions: # 23 | # The above copyright notice and this permission notice shall be included in # 24 | # all copies or substantial portions of the Software. # 25 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 26 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 27 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 28 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # 29 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 30 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 31 | # # 32 | ###################################################################################*/ 33 | 34 | 35 | #import "HTMLNode+XPath.h" 36 | #import 37 | #import 38 | 39 | static NSString *kXPathPredicateNode = @"/descendant::%@"; 40 | static NSString *kXPathPredicateNodeWithAttribute = @"//%@[@%@]"; 41 | static NSString *kXPathPredicateAttribute = @"//*[@%@]"; 42 | static NSString *kXPathPredicateAttributeIsEqual = @"//*[@%@ ='%@']"; 43 | static NSString *kXPathPredicateAttributeBeginsWith = @"//*[starts-with(@%@,'%@')]"; 44 | static NSString *kXPathPredicateAttributeEndsWith = @"//*['%@' = substring(@%@, string-length(@%@)- string-length('%@') +1)]"; 45 | static NSString *kXPathPredicateAttributeContains = @"//*[contains(@%@,'%@')]"; 46 | 47 | static id performXPathQuery(xmlNode * node, NSString * query, BOOL returnSingleNode, BOOL considerError, HTMLNode *htmlNode); 48 | static void XPathErrorCallback(void *node, xmlErrorPtr err); 49 | 50 | #pragma mark - static C functions 51 | 52 | // xpath error callback 53 | static void XPathErrorCallback(void *node, xmlErrorPtr err) 54 | { 55 | NSInteger errorCode = (NSInteger )err->code; 56 | if ((errorCode > 1199) && (errorCode < 1223)) { // filter XPath errors 1200 - 1222 57 | char *errMessage = err->message; 58 | NSString *errorMessage = (errMessage) ? [NSString stringWithUTF8String:errMessage] : @"unknown error"; 59 | #if __has_feature(objc_arc) 60 | [(__bridge_transfer HTMLNode *)node setErrorWithMessage:errorMessage andCode:errorCode]; 61 | #else 62 | [(HTMLNode *)node setErrorWithMessage:errorMessage andCode:errorCode]; 63 | #endif 64 | } 65 | } 66 | 67 | 68 | // performXPathQuery() returns one HTMLNode object or an array of HTMLNode objects 69 | // if the query matches any nodes, otherwise nil. 70 | 71 | static id performXPathQuery(xmlNode * node, NSString * query, BOOL returnSingleNode, BOOL considerError, HTMLNode *htmlNode) 72 | { 73 | if (query == nil) { 74 | if (considerError) [htmlNode setErrorWithMessage:@"query string must not be nil value" andCode:6]; 75 | return nil; 76 | } 77 | xmlXPathContextPtr xpathContext; 78 | xmlXPathObjectPtr xpathObject; 79 | id result = (returnSingleNode) ? nil : [NSMutableArray array]; 80 | 81 | xpathContext = xmlXPathNewContext((xmlDocPtr)node); 82 | if (xpathContext) { 83 | if (considerError) 84 | #if __has_feature(objc_arc) 85 | { xmlSetStructuredErrorFunc((__bridge_retained void *)htmlNode, XPathErrorCallback); } 86 | #else 87 | { xmlSetStructuredErrorFunc((void *)htmlNode, XPathErrorCallback); } 88 | #endif 89 | 90 | xpathObject = xmlXPathEvalExpression((xmlChar *)[query UTF8String], xpathContext); 91 | 92 | if (xpathObject) { 93 | xmlNodeSetPtr nodes = xpathObject->nodesetval; 94 | if (xmlXPathNodeSetIsEmpty(nodes) == NO) { 95 | if (returnSingleNode) { 96 | result = [HTMLNode nodeWithXMLNode:nodes->nodeTab[0]]; 97 | } else { 98 | 99 | 100 | for (int i = 0; i < nodes->nodeNr; i++) { 101 | HTMLNode *matchedNode = [[HTMLNode alloc] initWithXMLNode:nodes->nodeTab[i]]; 102 | [result addObject:matchedNode]; 103 | #if !__has_feature(objc_arc) 104 | [matchedNode release]; 105 | #endif 106 | } 107 | } 108 | } 109 | xmlXPathFreeObject(xpathObject); 110 | } 111 | else { 112 | if (considerError) [htmlNode setErrorWithMessage:@"Could not evaluate XPath expression" andCode:5]; 113 | } 114 | xmlXPathFreeContext(xpathContext); 115 | } 116 | else 117 | if (considerError) [htmlNode setErrorWithMessage:@"Could not create XPath context" andCode:4]; 118 | 119 | return result; 120 | } 121 | 122 | #pragma mark 123 | 124 | @implementation HTMLNode (XPath) 125 | 126 | #pragma mark - private getter 127 | 128 | - (xmlNode *)xmlNode 129 | { 130 | return xmlNode_; 131 | } 132 | 133 | #pragma mark - Objective-C wrapper for XPath Query function 134 | 135 | // perform XPath query and return first search result 136 | 137 | - (HTMLNode *)nodeForXPath:(NSString *)query error:(NSError **)error 138 | { 139 | self.xpathError = nil; 140 | HTMLNode *result = (HTMLNode *)performXPathQuery(xmlNode_, query, YES, error != nil, self); 141 | if (error) *error = xpathError; 142 | return result; 143 | } 144 | 145 | - (HTMLNode *)nodeForXPath:(NSString *)query 146 | { 147 | return [self nodeForXPath:query error:nil]; 148 | } 149 | 150 | 151 | // perform XPath query and return all results 152 | 153 | - (NSArray *)nodesForXPath:(NSString *)query error:(NSError **)error 154 | { 155 | self.xpathError = nil; 156 | NSArray *result = (NSArray *)performXPathQuery(xmlNode_, query, NO, error != nil, self); 157 | if (error) *error = xpathError; 158 | return result; 159 | } 160 | 161 | - (NSArray *)nodesForXPath:(NSString *)query 162 | { 163 | return [self nodesForXPath:query error:nil]; 164 | } 165 | 166 | #pragma mark - specific XPath Query methods 167 | 168 | - (HTMLNode *)nodeOfTag:(NSString *)tagName error:(NSError **)error 169 | { 170 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateNode, tagName] error:error]; 171 | } 172 | 173 | - (HTMLNode *)nodeOfTag:(NSString *)tagName 174 | { 175 | return [self nodeOfTag:tagName error:nil]; 176 | } 177 | 178 | - (NSArray *)nodesOfTag:(NSString *)tagName error:(NSError **)error 179 | { 180 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateNode, tagName] error:error]; 181 | } 182 | 183 | - (NSArray *)nodesOfTag:(NSString *)tagName 184 | { 185 | return [self nodesOfTag:tagName error:nil]; 186 | } 187 | 188 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName error:(NSError **)error 189 | { 190 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttribute, attributeName] error:error]; 191 | } 192 | 193 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName 194 | { 195 | return [self nodeWithAttribute:attributeName error:nil]; 196 | } 197 | 198 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName error:(NSError **)error 199 | { 200 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttribute, attributeName] error:error]; 201 | } 202 | 203 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName 204 | { 205 | return [self nodesWithAttribute:attributeName error:nil]; 206 | } 207 | 208 | - (HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error 209 | { 210 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateNodeWithAttribute, tagName, attributeName] error:error]; 211 | } 212 | 213 | - (HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName 214 | { 215 | return [self nodeOfTag:tagName withAttribute:attributeName error:nil]; 216 | } 217 | 218 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error 219 | { 220 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateNodeWithAttribute, tagName, attributeName] error:error]; 221 | } 222 | 223 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName 224 | { 225 | return [self nodesOfTag:tagName withAttribute:attributeName error:nil]; 226 | } 227 | 228 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error 229 | { 230 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeIsEqual, attributeName, value] error:error]; 231 | } 232 | 233 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value 234 | { 235 | return [self nodeWithAttribute:attributeName valueMatches:value error:nil]; 236 | } 237 | 238 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error 239 | { 240 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeIsEqual, attributeName, value] error:error]; 241 | } 242 | 243 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value 244 | { 245 | return [self nodesWithAttribute:attributeName valueMatches:value error:nil]; 246 | } 247 | 248 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error 249 | { 250 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeBeginsWith, attributeName, value] error:error]; 251 | } 252 | 253 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value 254 | { 255 | return [self nodeWithAttribute:attributeName valueBeginsWith:value error:nil]; 256 | } 257 | 258 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error 259 | { 260 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeBeginsWith, attributeName, value] error:error]; 261 | } 262 | 263 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value 264 | { 265 | return [self nodesWithAttribute:attributeName valueBeginsWith:value error:nil]; 266 | } 267 | 268 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error 269 | { 270 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeEndsWith, value, attributeName, attributeName, value] error:error]; 271 | } 272 | 273 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value 274 | { 275 | return [self nodeWithAttribute:attributeName valueEndsWith:value error:nil]; 276 | } 277 | 278 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error 279 | { 280 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeEndsWith, value, attributeName, attributeName, value] error:error]; 281 | } 282 | 283 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value 284 | { 285 | return [self nodesWithAttribute:attributeName valueEndsWith:value error:nil]; 286 | } 287 | 288 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error 289 | { 290 | return [self nodeForXPath:[NSString stringWithFormat:kXPathPredicateAttributeContains, attributeName, value] error:error]; 291 | } 292 | 293 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value 294 | { 295 | return [self nodeWithAttribute:attributeName valueContains:value error:nil]; 296 | } 297 | 298 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error 299 | { 300 | return [self nodesForXPath:[NSString stringWithFormat:kXPathPredicateAttributeContains, attributeName, value] error:error]; 301 | } 302 | 303 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value 304 | { 305 | return [self nodesWithAttribute:attributeName valueContains:value error:nil]; 306 | } 307 | 308 | - (HTMLNode *)nodeWithClass:(NSString *)classValue error:(NSError **)error 309 | { 310 | return [self nodeWithAttribute:kClassKey valueMatches:classValue error:error]; 311 | } 312 | 313 | - (HTMLNode *)nodeWithClass:(NSString *)classValue 314 | { 315 | return [self nodeWithAttribute:kClassKey valueMatches:classValue]; 316 | } 317 | 318 | - (NSArray *)nodesWithClass:(NSString *)classValue error:(NSError **)error 319 | { 320 | return [self nodesWithAttribute:kClassKey valueMatches:classValue error:error]; 321 | } 322 | 323 | - (NSArray *)nodesWithClass:(NSString *)classValue 324 | { 325 | return [self nodesWithAttribute:kClassKey valueMatches:classValue]; 326 | } 327 | 328 | #pragma mark - Overriding Equality 329 | 330 | //compare HTMLNode objects with XPath 331 | - (BOOL)isEqual:(HTMLNode *)node 332 | { 333 | if (node == self) return YES; 334 | if (!node || ![node isKindOfClass: [self class]]) return NO; 335 | return xmlXPathCmpNodes([self xmlNode], [node xmlNode]) == 0; 336 | } 337 | 338 | #pragma mark - error handling 339 | 340 | - (void)setErrorWithMessage:(NSString *)message andCode:(NSInteger)code 341 | { 342 | self.xpathError = [NSError errorWithDomain:@"com.klieme.HTMLDocument" 343 | code:code 344 | userInfo:@{NSLocalizedDescriptionKey: message}]; 345 | } 346 | 347 | @end 348 | -------------------------------------------------------------------------------- /Objective-C/Xcode-6/HTMLNode+XPath.h: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLNode+XPath.h # 4 | # Category of HTMLNode for XPath support # 5 | # # 6 | # Copyright © 2014 by Stefan Klieme # 7 | # # 8 | # Objective-C wrapper for HTML parser of libxml2 # 9 | # # 10 | # Version 1.7 - 20. Sep 2014 # 11 | # # 12 | # usage: add #import HTMLNode+XPath.h # 13 | # # 14 | # # 15 | ##################################################################################### 16 | # # 17 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 18 | # this software and associated documentation files (the "Software"), to deal # 19 | # in the Software without restriction, including without limitation the rights # 20 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 21 | # of the Software, and to permit persons to whom the Software is furnished to do # 22 | # so, subject to the following conditions: # 23 | # The above copyright notice and this permission notice shall be included in # 24 | # all copies or substantial portions of the Software. # 25 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 26 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 27 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 28 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # 29 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 30 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 31 | # # 32 | ###################################################################################*/ 33 | 34 | #import "HTMLNode.h" 35 | 36 | #if !defined(__clang__) || __clang_major__ < 3 37 | 38 | #ifndef __bridge_retained 39 | #define __bridge_retained 40 | #endif 41 | 42 | #ifndef __bridge_transfer 43 | #define __bridge_transfer 44 | #endif 45 | 46 | #endif 47 | 48 | 49 | @interface HTMLNode (XPath) 50 | 51 | // Xpath query methods 52 | 53 | 54 | /*! Returns the first descendant node for a XPath query 55 | * \param query The XPath query string 56 | * \param error An error object that, on return, identifies any Xpath errors. 57 | * \returns The first found descendant node or nil if no node matches the parameters 58 | */ 59 | - (HTMLNode *)nodeForXPath:(NSString *)query error:(NSError **)error; 60 | 61 | /*! Returns the first descendant node for a XPath query 62 | * \param query The XPath query string 63 | * \returns The first found descendant node or nil if no node matches the parameters 64 | */ 65 | - (HTMLNode *)nodeForXPath:(NSString *)query; 66 | 67 | /*! Returns all descendant nodes for a XPath query 68 | * \param query The XPath query string 69 | * \param error An error object that, on return, identifies any Xpath errors. 70 | * \returns The array of all found descendant nodes or an empty array 71 | */ 72 | - (NSArray *)nodesForXPath:(NSString *)query error:(NSError **)error; 73 | 74 | /*! Returns all descendant nodes for a XPath query 75 | * \param query The XPath query string 76 | * \returns The array of all found descendant nodes or an empty array 77 | */ 78 | - (NSArray *)nodesForXPath:(NSString *)query; 79 | 80 | // Note: In the HTMLNode main class all appropriate query methods begin with descendant instead of node 81 | 82 | /*! Returns the first descendant node for a specified tag name 83 | * \param tagName The tag name 84 | * \param error An error object that, on return, identifies any Xpath errors. 85 | * \returns The first found descendant node or nil if no node matches the parameters 86 | */ 87 | - (HTMLNode *)nodeOfTag:(NSString *)tagName error:(NSError **)error; 88 | 89 | /*! Returns the first descendant node for a specified tag name 90 | * \param tagName The tag name 91 | * \returns The first found descendant node or nil if no node matches the parameters 92 | */ 93 | - (HTMLNode *)nodeOfTag:(NSString *)tagName; 94 | 95 | /*! Returns all descendant nodes for a specified tag name 96 | * \param tagName The tag name 97 | * \param error An error object that, on return, identifies any Xpath errors. 98 | * \returns The array of all found descendant nodes or an empty array 99 | */ 100 | - (NSArray *)nodesOfTag:(NSString *)tagName error:(NSError **)error; 101 | 102 | /*! Returns all descendant nodes for a specified tag name 103 | * \param tagName The tag name 104 | * \returns The array of all found descendant nodes or an empty array 105 | */ 106 | - (NSArray *)nodesOfTag:(NSString *)tagName; 107 | 108 | /*! Returns the first descendant node for a matching tag name and matching attribute name 109 | * \param tagName The tag name 110 | * \param attributeName The attribute name 111 | * \param error An error object that, on return, identifies any Xpath errors. 112 | * \returns The first found descendant node or nil if no node matches the parameters 113 | */ 114 | - (HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error; 115 | 116 | /*! Returns the first descendant node for a matching tag name and matching attribute name 117 | * \param tagName The tag name 118 | * \param attributeName The attribute name 119 | * \returns The first found descendant node or nil if no node matches the parameters 120 | */ 121 | - (HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName; 122 | 123 | /*! Returns all descendant nodes for a matching tag name and matching attribute name 124 | * \param tagName The tag name 125 | * \param attributeName The attribute name 126 | * \param error An error object that, on return, identifies any Xpath errors. 127 | * \returns The array of all found descendant nodes or an empty array 128 | */ 129 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error; 130 | 131 | /*! Returns all descendant nodes for a matching tag name and matching attribute name 132 | * \param tagName The tag name 133 | * \param attributeName The attribute name 134 | * \param error An error object that, on return, identifies any Xpath errors. 135 | * \returns The array of all found descendant nodes or an empty array 136 | */ 137 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName; 138 | 139 | /*! Returns the first descendant node for a specified attribute name 140 | * \param attributeName The attribute name 141 | * \param error An error object that, on return, identifies any Xpath errors. 142 | * \returns The first found descendant node or nil if no node matches the parameters 143 | */ 144 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName error:(NSError **)error; 145 | 146 | /*! Returns the first descendant node for a specified attribute name 147 | * \param attributeName The attribute name 148 | * \returns The first found descendant node or nil if no node matches the parameters 149 | */ 150 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName; 151 | 152 | /*! Returns all descendant nodes for a specified attribute name 153 | * \param attributeName The attribute name 154 | * \returns The array of all found descendant nodes or an empty array 155 | */ 156 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName error:(NSError **)error; 157 | 158 | /*! Returns all descendant nodes for a specified attribute name 159 | * \param attributeName The attribute name 160 | * \param error An error object that, on return, identifies any Xpath errors. 161 | * \returns The array of all found descendant nodes or an empty array 162 | */ 163 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName; 164 | 165 | /*! Returns the first descendant node for a matching attribute name and matching attribute value 166 | * \param attributeName The attribute name 167 | * \param value The attribute value 168 | * \param error An error object that, on return, identifies any Xpath errors. 169 | * \returns The first found descendant node or nil if no node matches the parameters 170 | */ 171 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error; 172 | 173 | /*! Returns the first descendant node for a matching attribute name and matching attribute value 174 | * \param attributeName The attribute name 175 | * \param value The attribute value 176 | * \returns The first found descendant node or nil if no node matches the parameters 177 | */ 178 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value; 179 | 180 | /*! Returns all descendant nodes for a matching attribute name and matching attribute value 181 | * \param attributeName The attribute name 182 | * \param value The attribute value 183 | * \param error An error object that, on return, identifies any Xpath errors. 184 | * \returns The array of all found descendant nodes or an empty array 185 | */ 186 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error; 187 | 188 | /*! Returns all descendant nodes for a matching attribute name and matching attribute value 189 | * \param attributeName The attribute name 190 | * \param value The attribute value 191 | * \returns The array of all found descendant nodes or an empty array 192 | */ 193 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value; 194 | 195 | /*! Returns the first descendant node for a matching attribute name and beginning of the attribute value 196 | * \param attributeName The attribute name 197 | * \param value The attribute value 198 | * \param error An error object that, on return, identifies any Xpath errors. 199 | * \returns The first found descendant node or nil if no node matches the parameters 200 | */ 201 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error; 202 | 203 | /*! Returns the first descendant node for a matching attribute name and beginning of the attribute value 204 | * \param attributeName The attribute name 205 | * \param value The attribute value 206 | * \returns The first found descendant node or nil if no node matches the parameters 207 | */ 208 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value; 209 | 210 | /*! Returns all descendant nodes for a matching attribute name and beginning of the attribute value 211 | * \param attributeName The attribute name 212 | * \param value The attribute value 213 | * \param error An error object that, on return, identifies any Xpath errors. 214 | * \returns The array of all found descendant nodes or an empty array 215 | */ 216 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error; 217 | 218 | /*! Returns all descendant nodes for a matching attribute name and beginning of the attribute value 219 | * \param attributeName The attribute name 220 | * \param value The attribute value 221 | * \returns The array of all found descendant nodes or an empty array 222 | */ 223 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value; 224 | 225 | /*! Returns the first descendant node for a matching attribute name and ending of the attribute value 226 | * \param attributeName The attribute name 227 | * \param value The attribute value 228 | * \param error An error object that, on return, identifies any Xpath errors. 229 | * \returns The first found descendant node or nil if no node matches the parameters 230 | */ 231 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error; 232 | 233 | /*! Returns the first descendant node for a matching attribute name and ending of the attribute value 234 | * \param attributeName The attribute name 235 | * \param value The attribute value 236 | * \returns The first found descendant node or nil if no node matches the parameters 237 | */ 238 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value; 239 | 240 | /*! Returns all descendant nodes for a matching attribute name and ending of the attribute value 241 | * \param attributeName The attribute name 242 | * \param value The attribute value 243 | * \param error An error object that, on return, identifies any Xpath errors. 244 | * \returns The array of all found descendant nodes or an empty array 245 | */ 246 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error; 247 | 248 | /*! Returns all descendant nodes for a matching attribute name and ending of the attribute value 249 | * \param attributeName The attribute name 250 | * \param value The attribute value 251 | * \returns The array of all found descendant nodes or an empty array 252 | */ 253 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value; 254 | 255 | /*! Returns the first descendant node for a matching attribute name and containing the attribute value 256 | * \param attributeName The attribute name 257 | * \param value The attribute value 258 | * \param error An error object that, on return, identifies any Xpath errors. 259 | * \returns The first found descendant node or nil if no node matches the parameters 260 | */ 261 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error; 262 | 263 | /*! Returns the first descendant node for a matching attribute name and containing the attribute value 264 | * \param attributeName The attribute name 265 | * \param value The attribute value 266 | * \returns The first found descendant node or nil if no node matches the parameters 267 | */ 268 | - (HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value; 269 | 270 | /*! Returns all descendant nodes for a matching attribute name and containing the attribute value 271 | * \param attributeName The attribute name 272 | * \param value The attribute value 273 | * \param error An error object that, on return, identifies any Xpath errors. 274 | * \returns The array of all found descendant nodes or an empty array 275 | */ 276 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error; 277 | 278 | /*! Returns all descendant nodes for a matching attribute name and containing the attribute value 279 | * \param attributeName The attribute name 280 | * \param value The attribute value 281 | * \returns The array of all found descendant nodes or an empty array 282 | */ 283 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value; 284 | 285 | /*! Returns the first descendant node for a specified class name 286 | * \param classValue The class name 287 | * \param error An error object that, on return, identifies any Xpath errors. 288 | * \returns The first found descendant node or nil if no node matches the parameters 289 | */ 290 | - (HTMLNode *)nodeWithClass:(NSString *)classValue error:(NSError **)error; 291 | 292 | /*! Returns the first descendant node for a specified class name 293 | * \param classValue The class name 294 | * \returns The first found descendant node or nil if no node matches the parameters 295 | */ 296 | - (HTMLNode *)nodeWithClass:(NSString *)classValue; 297 | 298 | /*! Returns all descendant nodes for a specified class name 299 | * \param classValue The class name 300 | * \param error An error object that, on return, identifies any Xpath errors. 301 | * \returns The array of all found descendant nodes or an empty array 302 | */ 303 | - (NSArray *)nodesWithClass:(NSString *)classValue error:(NSError **)error; 304 | 305 | /*! Returns all descendant nodes for a specified class name 306 | * \param classValue The class name 307 | * \returns The array of all found descendant nodes or an empty array 308 | */ 309 | - (NSArray *)nodesWithClass:(NSString *)classValue; 310 | 311 | 312 | // Compare two nodes w.r.t document order with XPath 313 | /*! Returns a Boolean value that indicates whether the receiver is equal to another given object 314 | * \param node The node with which to compare the receiver 315 | * \returns YES if the receiver is equal to the node, otherwise NO. In effect returns NO if receiver is nil 316 | */ 317 | - (BOOL)isEqual:(HTMLNode *)node; 318 | 319 | 320 | - (void)setErrorWithMessage:(NSString *)message andCode:(NSInteger)code; 321 | 322 | @end 323 | -------------------------------------------------------------------------------- /Objective-C/Xcode7+/HTMLNode+XPath.h: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLNode+XPath.h # 4 | # Category of HTMLNode for XPath support # 5 | # # 6 | # Copyright © 2014 by Stefan Klieme # 7 | # # 8 | # Objective-C wrapper for HTML parser of libxml2 # 9 | # # 10 | # Version 1.8 - 14. Dez 2015 for Xcode 7+ # 11 | # # 12 | # usage: add #import HTMLNode+XPath.h # 13 | # # 14 | # # 15 | ##################################################################################### 16 | # # 17 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 18 | # this software and associated documentation files (the "Software"), to deal # 19 | # in the Software without restriction, including without limitation the rights # 20 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 21 | # of the Software, and to permit persons to whom the Software is furnished to do # 22 | # so, subject to the following conditions: # 23 | # The above copyright notice and this permission notice shall be included in # 24 | # all copies or substantial portions of the Software. # 25 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 26 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 27 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 28 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # 29 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 30 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 31 | # # 32 | ###################################################################################*/ 33 | 34 | #import "HTMLNode.h" 35 | 36 | #if !defined(__clang__) || __clang_major__ < 3 37 | 38 | #ifndef __bridge_retained 39 | #define __bridge_retained 40 | #endif 41 | 42 | #ifndef __bridge_transfer 43 | #define __bridge_transfer 44 | #endif 45 | 46 | #endif 47 | 48 | 49 | @interface HTMLNode (XPath) 50 | 51 | // Xpath query methods 52 | 53 | NS_ASSUME_NONNULL_BEGIN 54 | 55 | /*! Returns the first descendant node for a XPath query 56 | * \param query The XPath query string 57 | * \param error An error object that, on return, identifies any Xpath errors. 58 | * \returns The first found descendant node or nil if no node matches the parameters 59 | */ 60 | - (nullable HTMLNode *)nodeForXPath:(NSString *)query error:(NSError **)error; 61 | 62 | /*! Returns the first descendant node for a XPath query 63 | * \param query The XPath query string 64 | * \returns The first found descendant node or nil if no node matches the parameters 65 | */ 66 | - (nullable HTMLNode *)nodeForXPath:(NSString *)query; 67 | 68 | /*! Returns all descendant nodes for a XPath query 69 | * \param query The XPath query string 70 | * \param error An error object that, on return, identifies any Xpath errors. 71 | * \returns The array of all found descendant nodes or an empty array 72 | */ 73 | - (NSArray *)nodesForXPath:(NSString *)query error:(NSError **)error; 74 | 75 | /*! Returns all descendant nodes for a XPath query 76 | * \param query The XPath query string 77 | * \returns The array of all found descendant nodes or an empty array 78 | */ 79 | - (NSArray *)nodesForXPath:(NSString *)query; 80 | 81 | // Note: In the HTMLNode main class all appropriate query methods begin with descendant instead of node 82 | 83 | /*! Returns the first descendant node for a specified tag name 84 | * \param tagName The tag name 85 | * \param error An error object that, on return, identifies any Xpath errors. 86 | * \returns The first found descendant node or nil if no node matches the parameters 87 | */ 88 | - (nullable HTMLNode *)nodeOfTag:(NSString *)tagName error:(NSError **)error; 89 | 90 | /*! Returns the first descendant node for a specified tag name 91 | * \param tagName The tag name 92 | * \returns The first found descendant node or nil if no node matches the parameters 93 | */ 94 | - (nullable HTMLNode *)nodeOfTag:(NSString *)tagName; 95 | 96 | /*! Returns all descendant nodes for a specified tag name 97 | * \param tagName The tag name 98 | * \param error An error object that, on return, identifies any Xpath errors. 99 | * \returns The array of all found descendant nodes or an empty array 100 | */ 101 | - (NSArray *)nodesOfTag:(NSString *)tagName error:(NSError **)error; 102 | 103 | /*! Returns all descendant nodes for a specified tag name 104 | * \param tagName The tag name 105 | * \returns The array of all found descendant nodes or an empty array 106 | */ 107 | - (NSArray *)nodesOfTag:(NSString *)tagName; 108 | 109 | /*! Returns the first descendant node for a matching tag name and matching attribute name 110 | * \param tagName The tag name 111 | * \param attributeName The attribute name 112 | * \param error An error object that, on return, identifies any Xpath errors. 113 | * \returns The first found descendant node or nil if no node matches the parameters 114 | */ 115 | - (nullable HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error; 116 | 117 | /*! Returns the first descendant node for a matching tag name and matching attribute name 118 | * \param tagName The tag name 119 | * \param attributeName The attribute name 120 | * \returns The first found descendant node or nil if no node matches the parameters 121 | */ 122 | - (nullable HTMLNode *)nodeOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName; 123 | 124 | /*! Returns all descendant nodes for a matching tag name and matching attribute name 125 | * \param tagName The tag name 126 | * \param attributeName The attribute name 127 | * \param error An error object that, on return, identifies any Xpath errors. 128 | * \returns The array of all found descendant nodes or an empty array 129 | */ 130 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName error:(NSError **)error; 131 | 132 | /*! Returns all descendant nodes for a matching tag name and matching attribute name 133 | * \param tagName The tag name 134 | * \param attributeName The attribute name 135 | * \param error An error object that, on return, identifies any Xpath errors. 136 | * \returns The array of all found descendant nodes or an empty array 137 | */ 138 | - (NSArray *)nodesOfTag:(NSString *)tagName withAttribute:(NSString *)attributeName; 139 | 140 | /*! Returns the first descendant node for a specified attribute name 141 | * \param attributeName The attribute name 142 | * \param error An error object that, on return, identifies any Xpath errors. 143 | * \returns The first found descendant node or nil if no node matches the parameters 144 | */ 145 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName error:(NSError **)error; 146 | 147 | /*! Returns the first descendant node for a specified attribute name 148 | * \param attributeName The attribute name 149 | * \returns The first found descendant node or nil if no node matches the parameters 150 | */ 151 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName; 152 | 153 | /*! Returns all descendant nodes for a specified attribute name 154 | * \param attributeName The attribute name 155 | * \returns The array of all found descendant nodes or an empty array 156 | */ 157 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName error:(NSError **)error; 158 | 159 | /*! Returns all descendant nodes for a specified attribute name 160 | * \param attributeName The attribute name 161 | * \param error An error object that, on return, identifies any Xpath errors. 162 | * \returns The array of all found descendant nodes or an empty array 163 | */ 164 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName; 165 | 166 | /*! Returns the first descendant node for a matching attribute name and matching attribute value 167 | * \param attributeName The attribute name 168 | * \param value The attribute value 169 | * \param error An error object that, on return, identifies any Xpath errors. 170 | * \returns The first found descendant node or nil if no node matches the parameters 171 | */ 172 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error; 173 | 174 | /*! Returns the first descendant node for a matching attribute name and matching attribute value 175 | * \param attributeName The attribute name 176 | * \param value The attribute value 177 | * \returns The first found descendant node or nil if no node matches the parameters 178 | */ 179 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value; 180 | 181 | /*! Returns all descendant nodes for a matching attribute name and matching attribute value 182 | * \param attributeName The attribute name 183 | * \param value The attribute value 184 | * \param error An error object that, on return, identifies any Xpath errors. 185 | * \returns The array of all found descendant nodes or an empty array 186 | */ 187 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value error:(NSError **)error; 188 | 189 | /*! Returns all descendant nodes for a matching attribute name and matching attribute value 190 | * \param attributeName The attribute name 191 | * \param value The attribute value 192 | * \returns The array of all found descendant nodes or an empty array 193 | */ 194 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueMatches:(NSString *)value; 195 | 196 | /*! Returns the first descendant node for a matching attribute name and beginning of the attribute value 197 | * \param attributeName The attribute name 198 | * \param value The attribute value 199 | * \param error An error object that, on return, identifies any Xpath errors. 200 | * \returns The first found descendant node or nil if no node matches the parameters 201 | */ 202 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error; 203 | 204 | /*! Returns the first descendant node for a matching attribute name and beginning of the attribute value 205 | * \param attributeName The attribute name 206 | * \param value The attribute value 207 | * \returns The first found descendant node or nil if no node matches the parameters 208 | */ 209 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value; 210 | 211 | /*! Returns all descendant nodes for a matching attribute name and beginning of the attribute value 212 | * \param attributeName The attribute name 213 | * \param value The attribute value 214 | * \param error An error object that, on return, identifies any Xpath errors. 215 | * \returns The array of all found descendant nodes or an empty array 216 | */ 217 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value error:(NSError **)error; 218 | 219 | /*! Returns all descendant nodes for a matching attribute name and beginning of the attribute value 220 | * \param attributeName The attribute name 221 | * \param value The attribute value 222 | * \returns The array of all found descendant nodes or an empty array 223 | */ 224 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)value; 225 | 226 | /*! Returns the first descendant node for a matching attribute name and ending of the attribute value 227 | * \param attributeName The attribute name 228 | * \param value The attribute value 229 | * \param error An error object that, on return, identifies any Xpath errors. 230 | * \returns The first found descendant node or nil if no node matches the parameters 231 | */ 232 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error; 233 | 234 | /*! Returns the first descendant node for a matching attribute name and ending of the attribute value 235 | * \param attributeName The attribute name 236 | * \param value The attribute value 237 | * \returns The first found descendant node or nil if no node matches the parameters 238 | */ 239 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value; 240 | 241 | /*! Returns all descendant nodes for a matching attribute name and ending of the attribute value 242 | * \param attributeName The attribute name 243 | * \param value The attribute value 244 | * \param error An error object that, on return, identifies any Xpath errors. 245 | * \returns The array of all found descendant nodes or an empty array 246 | */ 247 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value error:(NSError **)error; 248 | 249 | /*! Returns all descendant nodes for a matching attribute name and ending of the attribute value 250 | * \param attributeName The attribute name 251 | * \param value The attribute value 252 | * \returns The array of all found descendant nodes or an empty array 253 | */ 254 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)value; 255 | 256 | /*! Returns the first descendant node for a matching attribute name and containing the attribute value 257 | * \param attributeName The attribute name 258 | * \param value The attribute value 259 | * \param error An error object that, on return, identifies any Xpath errors. 260 | * \returns The first found descendant node or nil if no node matches the parameters 261 | */ 262 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error; 263 | 264 | /*! Returns the first descendant node for a matching attribute name and containing the attribute value 265 | * \param attributeName The attribute name 266 | * \param value The attribute value 267 | * \returns The first found descendant node or nil if no node matches the parameters 268 | */ 269 | - (nullable HTMLNode *)nodeWithAttribute:(NSString *)attributeName valueContains:(NSString *)value; 270 | 271 | /*! Returns all descendant nodes for a matching attribute name and containing the attribute value 272 | * \param attributeName The attribute name 273 | * \param value The attribute value 274 | * \param error An error object that, on return, identifies any Xpath errors. 275 | * \returns The array of all found descendant nodes or an empty array 276 | */ 277 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value error:(NSError **)error; 278 | 279 | /*! Returns all descendant nodes for a matching attribute name and containing the attribute value 280 | * \param attributeName The attribute name 281 | * \param value The attribute value 282 | * \returns The array of all found descendant nodes or an empty array 283 | */ 284 | - (NSArray *)nodesWithAttribute:(NSString *)attributeName valueContains:(NSString *)value; 285 | 286 | /*! Returns the first descendant node for a specified class name 287 | * \param classValue The class name 288 | * \param error An error object that, on return, identifies any Xpath errors. 289 | * \returns The first found descendant node or nil if no node matches the parameters 290 | */ 291 | - (nullable HTMLNode *)nodeWithClass:(NSString *)classValue error:(NSError **)error; 292 | 293 | /*! Returns the first descendant node for a specified class name 294 | * \param classValue The class name 295 | * \returns The first found descendant node or nil if no node matches the parameters 296 | */ 297 | - (nullable HTMLNode *)nodeWithClass:(NSString *)classValue; 298 | 299 | /*! Returns all descendant nodes for a specified class name 300 | * \param classValue The class name 301 | * \param error An error object that, on return, identifies any Xpath errors. 302 | * \returns The array of all found descendant nodes or an empty array 303 | */ 304 | - (NSArray *)nodesWithClass:(NSString *)classValue error:(NSError **)error; 305 | 306 | /*! Returns all descendant nodes for a specified class name 307 | * \param classValue The class name 308 | * \returns The array of all found descendant nodes or an empty array 309 | */ 310 | - (NSArray *)nodesWithClass:(NSString *)classValue; 311 | 312 | 313 | // Compare two nodes w.r.t document order with XPath 314 | /*! Returns a Boolean value that indicates whether the receiver is equal to another given object 315 | * \param node The node with which to compare the receiver 316 | * \returns YES if the receiver is equal to the node, otherwise NO. In effect returns NO if receiver is nil 317 | */ 318 | - (BOOL)isEqual:(nullable HTMLNode *)node; 319 | 320 | 321 | - (void)setErrorWithMessage:(NSString *)message andCode:(NSInteger)code; 322 | 323 | NS_ASSUME_NONNULL_END 324 | 325 | @end 326 | -------------------------------------------------------------------------------- /Objective-C/Xcode-6/HTMLNode.h: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLNode.h # 4 | # # 5 | # Copyright © 2014 by Stefan Klieme # 6 | # # 7 | # Objective-C wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.7 - 20. Sep 2014 # 10 | # # 11 | # usage: add libxml2.dylib to frameworks # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # # 15 | # # 16 | #################################################################################### 17 | # # 18 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 19 | # this software and associated documentation files (the "Software"), to deal # 20 | # in the Software without restriction, including without limitation the rights # 21 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 22 | # of the Software, and to permit persons to whom the Software is furnished to do # 23 | # so, subject to the following conditions: # 24 | # The above copyright notice and this permission notice shall be included in # 25 | # all copies or substantial portions of the Software. # 26 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 27 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 28 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 29 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,# 30 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 31 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 32 | # # 33 | ##################################################################################*/ 34 | 35 | #import 36 | #import 37 | #import 38 | 39 | #define kClassKey @"class" 40 | #define kIDKey @"id" 41 | 42 | // ARCMacros by John Blanco 43 | // added a macro for computed readonly properties which return always autoreleased objects 44 | 45 | #if __has_feature(objc_arc) 46 | #define SAFE_ARC_PROP_RETAIN strong 47 | #define SAFE_ARC_READONLY_OBJ_PROP unsafe_unretained, readonly 48 | #define SAFE_ARC_RELEASE(x) 49 | #define SAFE_ARC_AUTORELEASE(x) (x) 50 | #define SAFE_ARC_SUPER_DEALLOC() 51 | #else 52 | #define SAFE_ARC_PROP_RETAIN retain 53 | #define SAFE_ARC_READONLY_OBJ_PROP readonly 54 | #define SAFE_ARC_RELEASE(x) ([(x) release]) 55 | #define SAFE_ARC_AUTORELEASE(x) ([(x) autorelease]) 56 | #define SAFE_ARC_SUPER_DEALLOC() ([super dealloc]) 57 | #endif 58 | 59 | #if __has_feature(objc_instancetype) 60 | #define INSTANCETYPE_OR_ID instancetype 61 | #else 62 | #define INSTANCETYPE_OR_ID id 63 | #endif 64 | 65 | @interface HTMLNode : NSObject { 66 | NSError *xpathError; 67 | xmlNode * xmlNode_; 68 | } 69 | 70 | /*! An XPath error*/ 71 | @property (SAFE_ARC_PROP_RETAIN) NSError *xpathError; 72 | 73 | #pragma mark - init methods 74 | #pragma mark class 75 | // Returns a HTMLNode object initialized with a xml node pointer of xmllib 76 | 77 | /*! Returns an HTMLNode object with a specified xmlNode pointer. 78 | * \param xmlNode The xmlNode pointer for the created node object 79 | * \returns An HTMLNode object 80 | */ 81 | + (HTMLNode *)nodeWithXMLNode:(xmlNode *)xmlNode; // convenience initializer 82 | 83 | #pragma mark instance 84 | /*! Initializes and returns a newly allocated HTMLNode object with a specified xmlNode pointer. 85 | * \param xmlNode The xmlNode pointer for the created node object 86 | * \returns An initizlized HTMLNode object or nil if the object couldn't be created 87 | */ 88 | - (INSTANCETYPE_OR_ID)initWithXMLNode:(xmlNode *)xmlNode; 89 | 90 | #pragma mark - navigation 91 | // Node navigation relative to current node (self) 92 | 93 | /*! The parent node 94 | * \returns The parent node or nil 95 | */ 96 | @property (SAFE_ARC_READONLY_OBJ_PROP) HTMLNode *parent; 97 | 98 | /*! The next sibling node 99 | * \returns The next sibling node or nil 100 | */ 101 | @property (SAFE_ARC_READONLY_OBJ_PROP) HTMLNode *nextSibling; 102 | 103 | /*! The previous sibling node 104 | * \returns The previous sibling or nil 105 | */ 106 | @property (SAFE_ARC_READONLY_OBJ_PROP) HTMLNode *previousSibling; 107 | 108 | /*! The first child node 109 | * \returns The first child or nil 110 | */ 111 | @property (SAFE_ARC_READONLY_OBJ_PROP) HTMLNode *firstChild; 112 | 113 | /*! The last child node 114 | * \returns The last child or nil 115 | */ 116 | @property (SAFE_ARC_READONLY_OBJ_PROP) HTMLNode *lastChild; 117 | 118 | /*! The first level of children 119 | * \returns The children array or an empty array 120 | */ 121 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSArray *children; 122 | 123 | /*! The number of children*/ 124 | @property (readonly) NSUInteger childCount; 125 | 126 | /*! The child node at specified index 127 | * \param index The specified index 128 | * \returns The child node or nil if the index is invalid 129 | */ 130 | - (HTMLNode *)childAtIndex:(NSUInteger)index; 131 | 132 | #pragma mark - attributes and values of current node (self) 133 | 134 | /*! The attribute value of a node matching a given name 135 | * \param attributeName A name of an attribute 136 | * \returns The attribute value or nil if the attribute could not be found 137 | */ 138 | - (NSString *)attributeForName:(NSString *)attributeName; 139 | 140 | /*! All attributes and values as dictionary 141 | * \returns a dictionary which could be empty if there are no attributes. Returns nil if the node is nil or is document node 142 | */ 143 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSDictionary *attributes; 144 | 145 | /*! The tag name 146 | * \returns The tag name or nil if the node is document node 147 | */ 148 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *tagName; 149 | 150 | /*! The value for the class attribute*/ 151 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *classValue; 152 | 153 | /*! The value for the id attribute*/ 154 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *IDValue; 155 | 156 | /*! The value for the href attribute*/ 157 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *hrefValue; 158 | 159 | /*! The value for the src attribute*/ 160 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *srcValue; 161 | 162 | /*! The integer value*/ 163 | @property (readonly) NSInteger integerValue; 164 | 165 | /*! The double value*/ 166 | @property (readonly) double doubleValue; 167 | 168 | /*! Returns the double value of the string value for a specified locale identifier 169 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 170 | * \returns The double value of the string value depending on the parameter 171 | */ 172 | - (double )doubleValueForLocaleIdentifier:(NSString *)identifier; 173 | 174 | /*! Returns the double value of the string value for a specified locale identifier considering a plus sign prefix 175 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 176 | * \param flag Considers the plus sign in the string if YES 177 | * \returns The double value of the string value depending on the parameters 178 | */ 179 | - (double )doubleValueForLocaleIdentifier:(NSString *)identifier consideringPlusSign:(BOOL)flag; 180 | 181 | /*! Returns the double value of the text content for a specified locale identifier 182 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 183 | * \returns The double value of the text content depending on the parameter 184 | */ 185 | - (double )contentDoubleValueForLocaleIdentifier:(NSString *)identifier; 186 | 187 | /*! Returns the double value of the text content for a specified locale identifier considering a plus sign prefix 188 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 189 | * \param flag Considers the plus sign in the string if YES 190 | * \returns The double value of the text content depending on the parameters 191 | */ 192 | - (double )contentDoubleValueForLocaleIdentifier:(NSString *)identifier consideringPlusSign:(BOOL)flag; 193 | 194 | /*! Returns the date value of the string value for a specified date format and time zone 195 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 196 | * \param timeZone A time zone 197 | * \returns The date value of the string value depending on the parameters 198 | */ 199 | - (NSDate *)dateValueForFormat:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone; 200 | 201 | /*! Returns the date value of the text content for a specified date format and time zone 202 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 203 | * \param timeZone A time zone 204 | * \returns The date value of the text content depending on the parameters 205 | */ 206 | - (NSDate *)contentDateValueForFormat:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone; 207 | 208 | /*! Returns the date value of the string value for a specified date format 209 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 210 | * \returns The date value of the string value depending on the parameter 211 | */ 212 | - (NSDate *)dateValueForFormat:(NSString *)dateFormat; 213 | 214 | /*! Returns the date value of the text content for a specified date format 215 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 216 | * \returns The date value of the text content depending on the parameter 217 | */ 218 | - (NSDate *)contentDateValueForFormat:(NSString *)dateFormat; 219 | 220 | /*! The raw string 221 | * \returns The raw string value or nil 222 | */ 223 | 224 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *rawStringValue; 225 | 226 | /*! The string value of a node trimmed by whitespace and newline characters 227 | * \returns The string value or nil 228 | */ 229 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *stringValue; 230 | 231 | /*! The string value of a node trimmed by whitespace and newline characters and collapsing all multiple occurrences of whitespace and newline characters within the string into a single space 232 | * \returns The trimmed and collapsed string value or nil 233 | */ 234 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *stringValueCollapsingWhitespace; 235 | 236 | /*! The raw html text dump 237 | * \returns The raw html text dump or nil 238 | */ 239 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *HTMLString; 240 | 241 | /*! The array of all text content of children 242 | * \returns The text content array - each array item is trimmed by whitespace and newline characters - or an empty array 243 | */ 244 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSArray *textContentOfChildren; 245 | 246 | /*! The element type of the node*/ 247 | @property (readonly) xmlElementType elementType; 248 | 249 | /*! Is the node an attribute node*/ 250 | @property (readonly) BOOL isAttributeNode; 251 | 252 | /*! Is the node a document node*/ 253 | @property (readonly) BOOL isDocumentNode; 254 | 255 | /*! Is the node an element node*/ 256 | @property (readonly) BOOL isElementNode; 257 | 258 | /*! Is the node a text node*/ 259 | @property (readonly) BOOL isTextNode; 260 | 261 | #pragma mark - contents of current node and its descendants (descendant-or-self) 262 | 263 | /*! The raw text content of descendant-or-self 264 | * \returns The raw text content of the node and all its descendants or nil 265 | */ 266 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *rawTextContent; 267 | 268 | /*! The text content of descendant-or-self trimmed by whitespace and newline characters 269 | * \returns The trimmed text content of the node and all its descendants or nil 270 | */ 271 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *textContent; 272 | 273 | /*! The text content of descendant-or-self trimmed by whitespace and newline characters and collapsing all multiple occurrences of whitespace and newline characters within the string into a single space 274 | * \returns The text content of the node and all its descendants trimmed and collapsed or nil 275 | */ 276 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *textContentCollapsingWhitespace; 277 | 278 | /*! The text content of descendant-or-self in an array, each item trimmed by whitespace and newline characters 279 | * \returns An array of all text content of the node and its descendants - each array item is trimmed by whitespace and newline characters - or nil 280 | */ 281 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSArray *textContentOfDescendants; 282 | 283 | /*! The raw html text dump of descendant-or-self 284 | * \returns The raw html text dump of the node and all its descendants or nil 285 | */ 286 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSString *HTMLContent; 287 | 288 | 289 | #pragma mark - Query method declarations 290 | 291 | // Note: In the category HTMLNode+XPath all appropriate query methods begin with node instead of descendant 292 | 293 | /*! Returns the first descendant node with the specifed attribute name and value matching exactly 294 | * \param attributeName The name of the attribute 295 | * \param attributeValue The value of the attribute 296 | * \returns The first found descendant node or nil if no node matches the parameters 297 | */ 298 | - (HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 299 | 300 | /*! Returns the first child node with the specifed attribute name and value matching exactly 301 | * \param attributeName The name of the attribute 302 | * \param attributeValue The value of the attribute 303 | * \returns The first found child node or nil if no node matches the parameters 304 | */ 305 | - (HTMLNode *)childWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 306 | 307 | /*! Returns the first sibling node with the specifed attribute name and value matching exactly 308 | * \param attributeName The name of the attribute 309 | * \param attributeValue The value of the attribute 310 | * \returns The first found sibling node or nil if no node matches the parameters 311 | */ 312 | - (HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 313 | 314 | /*! Returns the first descendant node with the specifed attribute name and the value contains the specified attribute value 315 | * \param attributeName The name of the attribute 316 | * \param attributeValue The partial string of the attribute value 317 | * \returns The first found descendant node or nil if no node matches the parameters 318 | */ 319 | - (HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 320 | 321 | /*! Returns the first child node with the specifed attribute name and the value contains the specified attribute value 322 | * \param attributeName The name of the attribute 323 | * \param attributeValue The partial string of the attribute value 324 | * \returns The first found child node or nil if no node matches the parameters 325 | */ 326 | - (HTMLNode *)childWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 327 | 328 | /*! Returns the first sibling node with the specifed attribute name and the value contains the specified attribute value 329 | * \param attributeName The name of the attribute 330 | * \param attributeValue The partial string of the attribute value 331 | * \returns The first found sibling node or nil if no node matches the parameters 332 | */ 333 | - (HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 334 | 335 | /*! Returns the first descendant node with the specifed attribute name and the value contains the specified attribute value 336 | * \param attributeName The name of the attribute 337 | * \param attributeValue The partial string of the attribute value 338 | * \returns The first found descendant node or nil if no node matches the parameters 339 | */ 340 | - (HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 341 | 342 | /*! Returns the first child node with the specifed attribute name and the value begins with the specified attribute value 343 | * \param attributeName The name of the attribute 344 | * \param attributeValue The partial string of the attribute value 345 | * \returns The first found child node or nil if no node matches the parameters 346 | */ 347 | - (HTMLNode *)childWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 348 | 349 | /*! Returns the first sibling node with the specifed attribute name and the value begins with the specified attribute value 350 | * \param attributeName The name of the attribute 351 | * \param attributeValue The partial string of the attribute value 352 | * \returns The first found sibling node or nil if no node matches the parameters 353 | */ 354 | - (HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 355 | 356 | /*! Returns the first descendant node with the specifed attribute name and the value ends with the specified attribute value 357 | * \param attributeName The name of the attribute 358 | * \param attributeValue The partial string of the attribute value 359 | * \returns The first found descendant node or nil if no node matches the parameters 360 | */ 361 | - (HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 362 | 363 | /*! Returns the first child node with the specifed attribute name and the value ends with the specified attribute value 364 | * \param attributeName The name of the attribute 365 | * \param attributeValue The partial string of the attribute value 366 | * \returns The first found child node or nil if no node matches the parameters 367 | */ 368 | - (HTMLNode *)childWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 369 | 370 | /*! Returns the first sibling node with the specifed attribute name and the value ends with the specified attribute value 371 | * \param attributeName The name of the attribute 372 | * \param attributeValue The partial string of the attribute value 373 | * \returns The first found sibling node or nil if no node matches the parameters 374 | */ 375 | - (HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 376 | 377 | 378 | /*! Returns all descendant nodes with the specifed attribute name and value matching exactly 379 | * \param attributeName The name of the attribute 380 | * \param attributeValue The value of the attribute 381 | * \returns The array of all found descendant nodes or an empty array 382 | */ 383 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 384 | 385 | /*! Returns all child nodes with the specifed attribute name and value matching exactly 386 | * \param attributeName The name of the attribute 387 | * \param attributeValue The value of the attribute 388 | * \returns The array of all found child nodes or an empty array 389 | */ 390 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 391 | 392 | /*! Returns all sibling nodes with the specifed attribute name and value matching exactly 393 | * \param attributeName The name of the attribute 394 | * \param attributeValue The value of the attribute 395 | * \returns The array of all found sibling nodes or an empty array 396 | */ 397 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 398 | 399 | /*! Returns all descendant nodes with the specifed attribute name and the value contains the specified attribute value 400 | * \param attributeName The name of the attribute 401 | * \param attributeValue The partial string of the attribute value 402 | * \returns The array of all found descendant nodes or an empty array 403 | */ 404 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 405 | 406 | /*! Returns all child nodes with the specifed attribute name and the value contains the specified attribute value 407 | * \param attributeName The name of the attribute 408 | * \param attributeValue The partial string of the attribute value 409 | * \returns The array of all found child nodes or an empty array 410 | */ 411 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 412 | 413 | /*! Returns all sibling nodes with the specifed attribute name and the value contains the specified attribute value 414 | * \param attributeName The name of the attribute 415 | * \param attributeValue The partial string of the attribute value 416 | * \returns The array of all found sibling nodes or an empty array 417 | */ 418 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 419 | 420 | /*! Returns all descendant nodes with the specifed attribute name and the value begins with the specified attribute value 421 | * \param attributeName The name of the attribute 422 | * \param attributeValue The partial string of the attribute value 423 | * \returns The array of all found descendant nodes or an empty array 424 | */ 425 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 426 | 427 | /*! Returns all child nodes with the specifed attribute name and the value begins with the specified attribute value 428 | * \param attributeName The name of the attribute 429 | * \param attributeValue The partial string of the attribute value 430 | * \returns The array of all found child nodes or an empty array 431 | */ 432 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 433 | 434 | /*! Returns all sibling nodes with the specifed attribute name and the value begins with the specified attribute value 435 | * \param attributeName The name of the attribute 436 | * \param attributeValue The partial string of the attribute value 437 | * \returns The array of all found sibling nodes or an empty array 438 | */ 439 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 440 | 441 | /*! Returns all descendant nodes with the specifed attribute name and the value ends with the specified attribute value 442 | * \param attributeName The name of the attribute 443 | * \param attributeValue The partial string of the attribute value 444 | * \returns The array of all found descendant nodes or an empty array 445 | */ 446 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 447 | 448 | /*! Returns all child nodes with the specifed attribute name and the value ends with the specified attribute value 449 | * \param attributeName The name of the attribute 450 | * \param attributeValue The partial string of the attribute value 451 | * \returns The array of all found child nodes or an empty array 452 | */ 453 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 454 | 455 | /*! Returns all sibling nodes with the specifed attribute name and the value ends with the specified attribute value 456 | * \param attributeName The name of the attribute 457 | * \param attributeValue The partial string of the attribute value 458 | * \returns The array of all found sibling nodes or an empty array 459 | */ 460 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 461 | 462 | /*! Returns the first descendant node with the specifed attribute name 463 | * \param attributeName The name of the attribute 464 | * \returns The first found descendant node or nil 465 | */ 466 | - (HTMLNode *)descendantWithAttribute:(NSString *)attributeName; 467 | 468 | /*! Returns the first child node with the specifed attribute name 469 | * \param attributeName The name of the attribute 470 | * \returns The first found child node or nil 471 | */ 472 | - (HTMLNode *)childWithAttribute:(NSString *)attributeName; 473 | 474 | /*! Returns the first sibling node with the specifed attribute name 475 | * \param attributeName The name of the attribute 476 | * \returns The first found sibling node or nil 477 | */ 478 | - (HTMLNode *)siblingWithAttribute:(NSString *)attributeName; 479 | 480 | /*! Returns all descendant nodes with the specifed attribute name 481 | * \param attributeName The name of the attribute 482 | * \returns The array of all found descendant nodes or an empty array 483 | */ 484 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName; 485 | 486 | /*! Returns all child nodes with the specifed attribute name 487 | * \param attributeName The name of the attribute 488 | * \returns The array of all found child nodes or an empty array 489 | */ 490 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName; 491 | 492 | /*! Returns all sibling nodes with the specifed attribute name 493 | * \param attributeName The name of the attribute 494 | * \returns The array of all found sibling nodes or an empty array 495 | */ 496 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName; 497 | 498 | /*! Returns the first descendant node with the specifed class value 499 | * \param classValue The name of the class 500 | * \returns The first found descendant node or nil 501 | */ 502 | - (HTMLNode *)descendantWithClass:(NSString *)classValue; 503 | 504 | /*! Returns the first child node with the specifed class value 505 | * \param classValue The name of the class 506 | * \returns The first found child node or nil 507 | */ 508 | - (HTMLNode *)childWithClass:(NSString *)classValue; 509 | 510 | /*! Returns the first sibling node with the specifed class value 511 | * \param classValue The name of the class 512 | * \returns The first found sibling node or nil 513 | */ 514 | - (HTMLNode *)siblingWithClass:(NSString *)classValue; 515 | 516 | /*! Returns all descendant nodes with the specifed class value 517 | * \param classValue The name of the class 518 | * \returns The array of all found descendant nodes or an empty array 519 | */ 520 | - (NSArray *)descendantsWithClass:(NSString *)classValue; 521 | 522 | /*! Returns all child nodes with the specifed class value 523 | * \param classValue The name of the class 524 | * \returns The array of all found child nodes or an empty array 525 | */ 526 | - (NSArray *)childrenWithClass:(NSString *)classValue; 527 | 528 | /*! Returns all sibling nodes with the specifed class value 529 | * \param classValue The name of the class 530 | * \returns The array of all found sibling nodes or an empty array 531 | */ 532 | - (NSArray *)siblingsWithClass:(NSString *)classValue; 533 | 534 | /*! Returns the first descendant node with the specifed id value 535 | * \param classValue The name of the class 536 | * \returns The first found descendant node or nil 537 | */ 538 | - (HTMLNode *)descendantWithID:(NSString *)IDValue; 539 | 540 | /*! Returns the first child node with the specifed id value 541 | * \param classValue The name of the class 542 | * \returns The first found child node or nil 543 | */ 544 | - (HTMLNode *)childWithID:(NSString *)IDValue; 545 | 546 | /*! Returns the first sibling node with the specifed id value 547 | * \param classValue The name of the class 548 | * \returns The first found sibling node or nil 549 | */ 550 | - (HTMLNode *)siblingWithID:(NSString *)IDValue; 551 | 552 | /*! Returns the first descendant node with the specifed tag name and string value matching exactly 553 | * \param tagName The name of the tag 554 | * \param value The string value of the tag 555 | * \returns The first found descendant node or nil if no node matches the parameters 556 | */ 557 | - (HTMLNode *)descendantOfTag:(NSString *)tagName valueMatches:(NSString *)value; 558 | 559 | /*! Returns the first child node with the specifed tag name and string value matching exactly 560 | * \param tagName The name of the tag 561 | * \param value The string value of the tag 562 | * \returns The first found child node or nil if no node matches the parameters 563 | */ 564 | - (HTMLNode *)childOfTag:(NSString *)tagName valueMatches:(NSString *)value; 565 | 566 | /*! Returns the first sibling node with the specifed tag name and string value matching exactly 567 | * \param tagName The name of the tag 568 | * \param value The string value of the tag 569 | * \returns The first found sibling node or nil if no node matches the parameters 570 | */ 571 | - (HTMLNode *)siblingOfTag:(NSString *)tagName valueMatches:(NSString *)value; 572 | 573 | /*! Returns all descendant nodes with the specifed tag name and string value matching exactly 574 | * \param tagName The name of the tag 575 | * \param value The string value of the tag 576 | * \returns The array of all found descendant nodes or an empty array 577 | */ 578 | - (NSArray *)descendantsOfTag:(NSString *)tagName valueMatches:(NSString *)value; 579 | 580 | /*! Returns all child nodes with the specifed tag name and string value matching exactly 581 | * \param tagName The name of the tag 582 | * \param value The string value of the tag 583 | * \returns The array of all found child nodes or an empty array 584 | */ 585 | - (NSArray *)childrenOfTag:(NSString *)tagName valueMatches:(NSString *)value; 586 | 587 | /*! Returns all sibling nodes with the specifed tag name and string value matching exactly 588 | * \param tagName The name of the tag 589 | * \param value The string value of the tag 590 | * \returns The array of all found sibling nodes or an empty array 591 | */ 592 | - (NSArray *)siblingsOfTag:(NSString *)tagName valueMatches:(NSString *)value; 593 | 594 | /*! Returns the first descendant node with the specifed attribute name and the string value contains the specified value 595 | * \param tagName The name of the attribute 596 | * \param value The partial string of the attribute value 597 | * \returns The first found descendant node or nil if no node matches the parameters 598 | */ 599 | - (HTMLNode *)descendantOfTag:(NSString *)tagName valueContains:(NSString *)value; 600 | 601 | /*! Returns the child node with the specifed attribute name and the string value contains the specified value 602 | * \param tagName The name of the attribute 603 | * \param value The partial string of the attribute value 604 | * \returns The first found child node or nil if no node matches the parameters 605 | */ 606 | - (HTMLNode *)childOfTag:(NSString *)tagName valueContains:(NSString *)value; 607 | 608 | /*! Returns the sibling node with the specifed attribute name and the string value contains the specified value 609 | * \param tagName The name of the attribute 610 | * \param value The partial string of the attribute value 611 | * \returns The first found sibling node or nil if no node matches the parameters 612 | */ 613 | - (HTMLNode *)siblingOfTag:(NSString *)tagName valueContains:(NSString *)value; 614 | 615 | /*! Returns all descendant nodes with the specifed attribute name and the string value contains the specified value 616 | * \param tagName The name of the attribute 617 | * \param value The partial string of the attribute value 618 | * \returns The array of all found descendant nodes or an empty array 619 | */ 620 | - (NSArray *)descendantsOfTag:(NSString *)tagName valueContains:(NSString *)value; 621 | 622 | /*! Returns all child nodes with the specifed attribute name and the string value contains the specified value 623 | * \param tagName The name of the attribute 624 | * \param value The partial string of the attribute value 625 | * \returns The array of all found child nodes or an empty array 626 | */ 627 | - (NSArray *)childrenOfTag:(NSString *)tagName valueContains:(NSString *)value; 628 | 629 | /*! Returns all sibling nodes with the specifed attribute name and the string value contains the specified value 630 | * \param tagName The name of the attribute 631 | * \param value The partial string of the attribute value 632 | * \returns The array of all found sibling nodes or an empty array 633 | */ 634 | - (NSArray *)siblingsOfTag:(NSString *)tagName valueContains:(NSString *)value; 635 | 636 | /*! Returns the first descendant node with the specifed tag name 637 | * \param tagName The name of the tag 638 | * \returns The first found descendant node or nil 639 | */ 640 | - (HTMLNode *)descendantOfTag:(NSString *)tagName; 641 | 642 | /*! Returns the first child node with the specifed tag name 643 | * \param tagName The name of the tag 644 | * \returns The first found child node or nil 645 | */ 646 | - (HTMLNode *)childOfTag:(NSString *)tagName; 647 | 648 | /*! Returns the first sibling node with the specifed tag name 649 | * \param tagName The name of the tag 650 | * \returns The first found sibling node or nil 651 | */ 652 | - (HTMLNode *)siblingOfTag:(NSString *)tagName; 653 | 654 | /*! Returns all descendant nodes with the specifed tag name 655 | * \param tagName The name of the tag 656 | * \returns The array of all found descendant nodes or an empty array 657 | */ 658 | - (NSArray *)descendantsOfTag:(NSString *)tagName; 659 | 660 | /*! Returns all child nodes with the specifed tag name 661 | * \param tagName The name of the tag 662 | * \returns The array of all found child nodes or an empty array 663 | */ 664 | 665 | - (NSArray *)childrenOfTag:(NSString *)tagName; 666 | 667 | /*! Returns all sibling nodes with the specifed tag name 668 | * \param tagName The name of the tag 669 | * \returns The array of all found sibling nodes or an empty array 670 | */ 671 | - (NSArray *)siblingsOfTag:(NSString *)tagName; 672 | 673 | 674 | @end 675 | -------------------------------------------------------------------------------- /Objective-C/Xcode7+/HTMLNode.h: -------------------------------------------------------------------------------- 1 | /*################################################################################### 2 | # # 3 | # HTMLNode.h # 4 | # # 5 | # Copyright © 2014 by Stefan Klieme # 6 | # # 7 | # Objective-C wrapper for HTML parser of libxml2 # 8 | # # 9 | # Version 1.8 - 14. Dez 2015 for Xcode 7+ # 10 | # # 11 | # usage: add libxml2.dylib to frameworks # 12 | # add $SDKROOT/usr/include/libxml2 to target -> Header Search Paths # 13 | # add -lxml2 to target -> other linker flags # 14 | # # 15 | # # 16 | #################################################################################### 17 | # # 18 | # Permission is hereby granted, free of charge, to any person obtaining a copy of # 19 | # this software and associated documentation files (the "Software"), to deal # 20 | # in the Software without restriction, including without limitation the rights # 21 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # 22 | # of the Software, and to permit persons to whom the Software is furnished to do # 23 | # so, subject to the following conditions: # 24 | # The above copyright notice and this permission notice shall be included in # 25 | # all copies or substantial portions of the Software. # 26 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 27 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 28 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 29 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,# 30 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # 31 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # 32 | # # 33 | ##################################################################################*/ 34 | 35 | #import 36 | #import 37 | #import 38 | 39 | #define kClassKey @"class" 40 | #define kIDKey @"id" 41 | 42 | // ARCMacros by John Blanco 43 | // added a macro for computed readonly properties which return always autoreleased objects 44 | 45 | #if __has_feature(objc_arc) 46 | #define SAFE_ARC_PROP_RETAIN strong 47 | #define SAFE_ARC_READONLY_OBJ_PROP unsafe_unretained, readonly 48 | #define SAFE_ARC_RELEASE(x) 49 | #define SAFE_ARC_AUTORELEASE(x) (x) 50 | #define SAFE_ARC_SUPER_DEALLOC() 51 | #else 52 | #define SAFE_ARC_PROP_RETAIN retain 53 | #define SAFE_ARC_READONLY_OBJ_PROP readonly 54 | #define SAFE_ARC_RELEASE(x) ([(x) release]) 55 | #define SAFE_ARC_AUTORELEASE(x) ([(x) autorelease]) 56 | #define SAFE_ARC_SUPER_DEALLOC() ([super dealloc]) 57 | #endif 58 | 59 | #if __has_feature(objc_instancetype) 60 | #define INSTANCETYPE_OR_ID instancetype 61 | #else 62 | #define INSTANCETYPE_OR_ID id 63 | #endif 64 | 65 | @interface HTMLNode : NSObject { 66 | NSError * xpathError; 67 | xmlNode * xmlNode_; 68 | } 69 | 70 | NS_ASSUME_NONNULL_BEGIN 71 | 72 | /*! An XPath error*/ 73 | @property (SAFE_ARC_PROP_RETAIN, nullable) NSError *xpathError; 74 | 75 | #pragma mark - init methods 76 | #pragma mark class 77 | // Returns a HTMLNode object initialized with a xml node pointer of xmllib 78 | 79 | /*! Returns an HTMLNode object with a specified xmlNode pointer. 80 | * \param xmlNode The xmlNode pointer for the created node object 81 | * \returns An HTMLNode object 82 | */ 83 | + (HTMLNode *)nodeWithXMLNode:(xmlNode *)xmlNode; // convenience initializer 84 | 85 | #pragma mark instance 86 | /*! Initializes and returns a newly allocated HTMLNode object with a specified xmlNode pointer. 87 | * \param xmlNode The xmlNode pointer for the created node object 88 | * \returns An initizlized HTMLNode object or nil if the object couldn't be created 89 | */ 90 | - (INSTANCETYPE_OR_ID)initWithXMLNode:(xmlNode *)xmlNode; 91 | 92 | #pragma mark - navigation 93 | // Node navigation relative to current node (self) 94 | 95 | /*! The parent node 96 | * \returns The parent node or nil 97 | */ 98 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) HTMLNode *parent; 99 | 100 | /*! The next sibling node 101 | * \returns The next sibling node or nil 102 | */ 103 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) HTMLNode *nextSibling; 104 | 105 | /*! The previous sibling node 106 | * \returns The previous sibling or nil 107 | */ 108 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) HTMLNode *previousSibling; 109 | 110 | /*! The first child node 111 | * \returns The first child or nil 112 | */ 113 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) HTMLNode *firstChild; 114 | 115 | /*! The last child node 116 | * \returns The last child or nil 117 | */ 118 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) HTMLNode *lastChild; 119 | 120 | /*! The first level of children 121 | * \returns The children array or an empty array 122 | */ 123 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSArray *children; 124 | 125 | /*! The number of children*/ 126 | @property (readonly) NSUInteger childCount; 127 | 128 | /*! The child node at specified index 129 | * \param index The specified index 130 | * \returns The child node or nil if the index is invalid 131 | */ 132 | - (nullable HTMLNode *)childAtIndex:(NSUInteger)index; 133 | 134 | #pragma mark - attributes and values of current node (self) 135 | 136 | /*! The attribute value of a node matching a given name 137 | * \param attributeName A name of an attribute 138 | * \returns The attribute value or nil if the attribute could not be found 139 | */ 140 | - (nullable NSString *)attributeForName:(NSString *)attributeName; 141 | 142 | /*! All attributes and values as dictionary 143 | * \returns a dictionary which could be empty if there are no attributes. Returns nil if the node is nil or is document node 144 | */ 145 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSDictionary *attributes; 146 | 147 | /*! The tag name 148 | * \returns The tag name or nil if the node is document node 149 | */ 150 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *tagName; 151 | 152 | /*! The value for the class attribute*/ 153 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *classValue; 154 | 155 | /*! The value for the id attribute*/ 156 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *IDValue; 157 | 158 | /*! The value for the href attribute*/ 159 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *hrefValue; 160 | 161 | /*! The value for the src attribute*/ 162 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *srcValue; 163 | 164 | /*! The integer value*/ 165 | @property (readonly) NSInteger integerValue; 166 | 167 | /*! The double value*/ 168 | @property (readonly) double doubleValue; 169 | 170 | /*! Returns the double value of the string value for a specified locale identifier 171 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 172 | * \returns The double value of the string value depending on the parameter 173 | */ 174 | - (double )doubleValueForLocaleIdentifier:(NSString *)identifier; 175 | 176 | /*! Returns the double value of the string value for a specified locale identifier considering a plus sign prefix 177 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 178 | * \param flag Considers the plus sign in the string if YES 179 | * \returns The double value of the string value depending on the parameters 180 | */ 181 | - (double )doubleValueForLocaleIdentifier:(NSString *)identifier consideringPlusSign:(BOOL)flag; 182 | 183 | /*! Returns the double value of the text content for a specified locale identifier 184 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 185 | * \returns The double value of the text content depending on the parameter 186 | */ 187 | - (double )contentDoubleValueForLocaleIdentifier:(NSString *)identifier; 188 | 189 | /*! Returns the double value of the text content for a specified locale identifier considering a plus sign prefix 190 | * \param identifier A locale identifier. The locale identifier must conform to http://www.iso.org/iso/country_names_and_code_elements and http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 191 | * \param flag Considers the plus sign in the string if YES 192 | * \returns The double value of the text content depending on the parameters 193 | */ 194 | - (double )contentDoubleValueForLocaleIdentifier:(NSString *)identifier consideringPlusSign:(BOOL)flag; 195 | 196 | /*! Returns the date value of the string value for a specified date format and time zone 197 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 198 | * \param timeZone A time zone 199 | * \returns The date value of the string value depending on the parameters 200 | */ 201 | - (nullable NSDate *)dateValueForFormat:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone; 202 | 203 | /*! Returns the date value of the text content for a specified date format and time zone 204 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 205 | * \param timeZone A time zone 206 | * \returns The date value of the text content depending on the parameters 207 | */ 208 | - (nullable NSDate *)contentDateValueForFormat:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone; 209 | 210 | /*! Returns the date value of the string value for a specified date format 211 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 212 | * \returns The date value of the string value depending on the parameter 213 | */ 214 | - (nullable NSDate *)dateValueForFormat:(NSString *)dateFormat; 215 | 216 | /*! Returns the date value of the text content for a specified date format 217 | * \param dateFormat A date format string. The date format must conform to http://unicode.org/reports/tr35/tr35-10.html#Date_Format_Patterns 218 | * \returns The date value of the text content depending on the parameter 219 | */ 220 | - (nullable NSDate *)contentDateValueForFormat:(NSString *)dateFormat; 221 | 222 | /*! The raw string 223 | * \returns The raw string value or nil 224 | */ 225 | 226 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *rawStringValue; 227 | 228 | /*! The string value of a node trimmed by whitespace and newline characters 229 | * \returns The string value or nil 230 | */ 231 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *stringValue; 232 | 233 | /*! The string value of a node trimmed by whitespace and newline characters and collapsing all multiple occurrences of whitespace and newline characters within the string into a single space 234 | * \returns The trimmed and collapsed string value or nil 235 | */ 236 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *stringValueCollapsingWhitespace; 237 | 238 | /*! The raw html text dump 239 | * \returns The raw html text dump or nil 240 | */ 241 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *HTMLString; 242 | 243 | /*! The array of all text content of children 244 | * \returns The text content array - each array item is trimmed by whitespace and newline characters - or an empty array 245 | */ 246 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSArray *textContentOfChildren; 247 | 248 | /*! The element type of the node*/ 249 | @property (readonly) xmlElementType elementType; 250 | 251 | /*! Is the node an attribute node*/ 252 | @property (readonly) BOOL isAttributeNode; 253 | 254 | /*! Is the node a document node*/ 255 | @property (readonly) BOOL isDocumentNode; 256 | 257 | /*! Is the node an element node*/ 258 | @property (readonly) BOOL isElementNode; 259 | 260 | /*! Is the node a text node*/ 261 | @property (readonly) BOOL isTextNode; 262 | 263 | #pragma mark - contents of current node and its descendants (descendant-or-self) 264 | 265 | /*! The raw text content of descendant-or-self 266 | * \returns The raw text content of the node and all its descendants or nil 267 | */ 268 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *rawTextContent; 269 | 270 | /*! The text content of descendant-or-self trimmed by whitespace and newline characters 271 | * \returns The trimmed text content of the node and all its descendants or nil 272 | */ 273 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *textContent; 274 | 275 | /*! The text content of descendant-or-self trimmed by whitespace and newline characters and collapsing all multiple occurrences of whitespace and newline characters within the string into a single space 276 | * \returns The text content of the node and all its descendants trimmed and collapsed or nil 277 | */ 278 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *textContentCollapsingWhitespace; 279 | 280 | /*! The text content of descendant-or-self in an array, each item trimmed by whitespace and newline characters 281 | * \returns An array of all text content of the node and its descendants - each array item is trimmed by whitespace and newline characters - or nil 282 | */ 283 | @property (SAFE_ARC_READONLY_OBJ_PROP) NSArray *textContentOfDescendants; 284 | 285 | /*! The raw html text dump of descendant-or-self 286 | * \returns The raw html text dump of the node and all its descendants or nil 287 | */ 288 | @property (SAFE_ARC_READONLY_OBJ_PROP, nullable) NSString *HTMLContent; 289 | 290 | 291 | #pragma mark - Query method declarations 292 | 293 | // Note: In the category HTMLNode+XPath all appropriate query methods begin with node instead of descendant 294 | 295 | /*! Returns the first descendant node with the specifed attribute name and value matching exactly 296 | * \param attributeName The name of the attribute 297 | * \param attributeValue The value of the attribute 298 | * \returns The first found descendant node or nil if no node matches the parameters 299 | */ 300 | - (nullable HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 301 | 302 | /*! Returns the first child node with the specifed attribute name and value matching exactly 303 | * \param attributeName The name of the attribute 304 | * \param attributeValue The value of the attribute 305 | * \returns The first found child node or nil if no node matches the parameters 306 | */ 307 | - (nullable HTMLNode *)childWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 308 | 309 | /*! Returns the first sibling node with the specifed attribute name and value matching exactly 310 | * \param attributeName The name of the attribute 311 | * \param attributeValue The value of the attribute 312 | * \returns The first found sibling node or nil if no node matches the parameters 313 | */ 314 | - (nullable HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 315 | 316 | /*! Returns the first descendant node with the specifed attribute name and the value contains the specified attribute value 317 | * \param attributeName The name of the attribute 318 | * \param attributeValue The partial string of the attribute value 319 | * \returns The first found descendant node or nil if no node matches the parameters 320 | */ 321 | - (nullable HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 322 | 323 | /*! Returns the first child node with the specifed attribute name and the value contains the specified attribute value 324 | * \param attributeName The name of the attribute 325 | * \param attributeValue The partial string of the attribute value 326 | * \returns The first found child node or nil if no node matches the parameters 327 | */ 328 | - (nullable HTMLNode *)childWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 329 | 330 | /*! Returns the first sibling node with the specifed attribute name and the value contains the specified attribute value 331 | * \param attributeName The name of the attribute 332 | * \param attributeValue The partial string of the attribute value 333 | * \returns The first found sibling node or nil if no node matches the parameters 334 | */ 335 | - (nullable HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 336 | 337 | /*! Returns the first descendant node with the specifed attribute name and the value contains the specified attribute value 338 | * \param attributeName The name of the attribute 339 | * \param attributeValue The partial string of the attribute value 340 | * \returns The first found descendant node or nil if no node matches the parameters 341 | */ 342 | - (nullable HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 343 | 344 | /*! Returns the first child node with the specifed attribute name and the value begins with the specified attribute value 345 | * \param attributeName The name of the attribute 346 | * \param attributeValue The partial string of the attribute value 347 | * \returns The first found child node or nil if no node matches the parameters 348 | */ 349 | - (nullable HTMLNode *)childWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 350 | 351 | /*! Returns the first sibling node with the specifed attribute name and the value begins with the specified attribute value 352 | * \param attributeName The name of the attribute 353 | * \param attributeValue The partial string of the attribute value 354 | * \returns The first found sibling node or nil if no node matches the parameters 355 | */ 356 | - (nullable HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 357 | 358 | /*! Returns the first descendant node with the specifed attribute name and the value ends with the specified attribute value 359 | * \param attributeName The name of the attribute 360 | * \param attributeValue The partial string of the attribute value 361 | * \returns The first found descendant node or nil if no node matches the parameters 362 | */ 363 | - (nullable HTMLNode *)descendantWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 364 | 365 | /*! Returns the first child node with the specifed attribute name and the value ends with the specified attribute value 366 | * \param attributeName The name of the attribute 367 | * \param attributeValue The partial string of the attribute value 368 | * \returns The first found child node or nil if no node matches the parameters 369 | */ 370 | - (nullable HTMLNode *)childWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 371 | 372 | /*! Returns the first sibling node with the specifed attribute name and the value ends with the specified attribute value 373 | * \param attributeName The name of the attribute 374 | * \param attributeValue The partial string of the attribute value 375 | * \returns The first found sibling node or nil if no node matches the parameters 376 | */ 377 | - (nullable HTMLNode *)siblingWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 378 | 379 | 380 | /*! Returns all descendant nodes with the specifed attribute name and value matching exactly 381 | * \param attributeName The name of the attribute 382 | * \param attributeValue The value of the attribute 383 | * \returns The array of all found descendant nodes or an empty array 384 | */ 385 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 386 | 387 | /*! Returns all child nodes with the specifed attribute name and value matching exactly 388 | * \param attributeName The name of the attribute 389 | * \param attributeValue The value of the attribute 390 | * \returns The array of all found child nodes or an empty array 391 | */ 392 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 393 | 394 | /*! Returns all sibling nodes with the specifed attribute name and value matching exactly 395 | * \param attributeName The name of the attribute 396 | * \param attributeValue The value of the attribute 397 | * \returns The array of all found sibling nodes or an empty array 398 | */ 399 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueMatches:(NSString *)attributeValue; 400 | 401 | /*! Returns all descendant nodes with the specifed attribute name and the value contains the specified attribute value 402 | * \param attributeName The name of the attribute 403 | * \param attributeValue The partial string of the attribute value 404 | * \returns The array of all found descendant nodes or an empty array 405 | */ 406 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 407 | 408 | /*! Returns all child nodes with the specifed attribute name and the value contains the specified attribute value 409 | * \param attributeName The name of the attribute 410 | * \param attributeValue The partial string of the attribute value 411 | * \returns The array of all found child nodes or an empty array 412 | */ 413 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 414 | 415 | /*! Returns all sibling nodes with the specifed attribute name and the value contains the specified attribute value 416 | * \param attributeName The name of the attribute 417 | * \param attributeValue The partial string of the attribute value 418 | * \returns The array of all found sibling nodes or an empty array 419 | */ 420 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueContains:(NSString *)attributeValue; 421 | 422 | /*! Returns all descendant nodes with the specifed attribute name and the value begins with the specified attribute value 423 | * \param attributeName The name of the attribute 424 | * \param attributeValue The partial string of the attribute value 425 | * \returns The array of all found descendant nodes or an empty array 426 | */ 427 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 428 | 429 | /*! Returns all child nodes with the specifed attribute name and the value begins with the specified attribute value 430 | * \param attributeName The name of the attribute 431 | * \param attributeValue The partial string of the attribute value 432 | * \returns The array of all found child nodes or an empty array 433 | */ 434 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 435 | 436 | /*! Returns all sibling nodes with the specifed attribute name and the value begins with the specified attribute value 437 | * \param attributeName The name of the attribute 438 | * \param attributeValue The partial string of the attribute value 439 | * \returns The array of all found sibling nodes or an empty array 440 | */ 441 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueBeginsWith:(NSString *)attributeValue; 442 | 443 | /*! Returns all descendant nodes with the specifed attribute name and the value ends with the specified attribute value 444 | * \param attributeName The name of the attribute 445 | * \param attributeValue The partial string of the attribute value 446 | * \returns The array of all found descendant nodes or an empty array 447 | */ 448 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 449 | 450 | /*! Returns all child nodes with the specifed attribute name and the value ends with the specified attribute value 451 | * \param attributeName The name of the attribute 452 | * \param attributeValue The partial string of the attribute value 453 | * \returns The array of all found child nodes or an empty array 454 | */ 455 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 456 | 457 | /*! Returns all sibling nodes with the specifed attribute name and the value ends with the specified attribute value 458 | * \param attributeName The name of the attribute 459 | * \param attributeValue The partial string of the attribute value 460 | * \returns The array of all found sibling nodes or an empty array 461 | */ 462 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName valueEndsWith:(NSString *)attributeValue; 463 | 464 | /*! Returns the first descendant node with the specifed attribute name 465 | * \param attributeName The name of the attribute 466 | * \returns The first found descendant node or nil 467 | */ 468 | - (nullable HTMLNode *)descendantWithAttribute:(NSString *)attributeName; 469 | 470 | /*! Returns the first child node with the specifed attribute name 471 | * \param attributeName The name of the attribute 472 | * \returns The first found child node or nil 473 | */ 474 | - (nullable HTMLNode *)childWithAttribute:(NSString *)attributeName; 475 | 476 | /*! Returns the first sibling node with the specifed attribute name 477 | * \param attributeName The name of the attribute 478 | * \returns The first found sibling node or nil 479 | */ 480 | - (nullable HTMLNode *)siblingWithAttribute:(NSString *)attributeName; 481 | 482 | /*! Returns all descendant nodes with the specifed attribute name 483 | * \param attributeName The name of the attribute 484 | * \returns The array of all found descendant nodes or an empty array 485 | */ 486 | - (NSArray *)descendantsWithAttribute:(NSString *)attributeName; 487 | 488 | /*! Returns all child nodes with the specifed attribute name 489 | * \param attributeName The name of the attribute 490 | * \returns The array of all found child nodes or an empty array 491 | */ 492 | - (NSArray *)childrenWithAttribute:(NSString *)attributeName; 493 | 494 | /*! Returns all sibling nodes with the specifed attribute name 495 | * \param attributeName The name of the attribute 496 | * \returns The array of all found sibling nodes or an empty array 497 | */ 498 | - (NSArray *)siblingsWithAttribute:(NSString *)attributeName; 499 | 500 | /*! Returns the first descendant node with the specifed class value 501 | * \param classValue The name of the class 502 | * \returns The first found descendant node or nil 503 | */ 504 | - (nullable HTMLNode *)descendantWithClass:(NSString *)classValue; 505 | 506 | /*! Returns the first child node with the specifed class value 507 | * \param classValue The name of the class 508 | * \returns The first found child node or nil 509 | */ 510 | - (nullable HTMLNode *)childWithClass:(NSString *)classValue; 511 | 512 | /*! Returns the first sibling node with the specifed class value 513 | * \param classValue The name of the class 514 | * \returns The first found sibling node or nil 515 | */ 516 | - (nullable HTMLNode *)siblingWithClass:(NSString *)classValue; 517 | 518 | /*! Returns all descendant nodes with the specifed class value 519 | * \param classValue The name of the class 520 | * \returns The array of all found descendant nodes or an empty array 521 | */ 522 | - (NSArray *)descendantsWithClass:(NSString *)classValue; 523 | 524 | /*! Returns all child nodes with the specifed class value 525 | * \param classValue The name of the class 526 | * \returns The array of all found child nodes or an empty array 527 | */ 528 | - (NSArray *)childrenWithClass:(NSString *)classValue; 529 | 530 | /*! Returns all sibling nodes with the specifed class value 531 | * \param classValue The name of the class 532 | * \returns The array of all found sibling nodes or an empty array 533 | */ 534 | - (NSArray *)siblingsWithClass:(NSString *)classValue; 535 | 536 | /*! Returns the first descendant node with the specifed id value 537 | * \param classValue The name of the class 538 | * \returns The first found descendant node or nil 539 | */ 540 | - (nullable HTMLNode *)descendantWithID:(NSString *)IDValue; 541 | 542 | /*! Returns the first child node with the specifed id value 543 | * \param classValue The name of the class 544 | * \returns The first found child node or nil 545 | */ 546 | - (nullable HTMLNode *)childWithID:(NSString *)IDValue; 547 | 548 | /*! Returns the first sibling node with the specifed id value 549 | * \param classValue The name of the class 550 | * \returns The first found sibling node or nil 551 | */ 552 | - (nullable HTMLNode *)siblingWithID:(NSString *)IDValue; 553 | 554 | /*! Returns the first descendant node with the specifed tag name and string value matching exactly 555 | * \param tagName The name of the tag 556 | * \param value The string value of the tag 557 | * \returns The first found descendant node or nil if no node matches the parameters 558 | */ 559 | - (nullable HTMLNode *)descendantOfTag:(NSString *)tagName valueMatches:(NSString *)value; 560 | 561 | /*! Returns the first child node with the specifed tag name and string value matching exactly 562 | * \param tagName The name of the tag 563 | * \param value The string value of the tag 564 | * \returns The first found child node or nil if no node matches the parameters 565 | */ 566 | - (nullable HTMLNode *)childOfTag:(NSString *)tagName valueMatches:(NSString *)value; 567 | 568 | /*! Returns the first sibling node with the specifed tag name and string value matching exactly 569 | * \param tagName The name of the tag 570 | * \param value The string value of the tag 571 | * \returns The first found sibling node or nil if no node matches the parameters 572 | */ 573 | - (nullable HTMLNode *)siblingOfTag:(NSString *)tagName valueMatches:(NSString *)value; 574 | 575 | /*! Returns all descendant nodes with the specifed tag name and string value matching exactly 576 | * \param tagName The name of the tag 577 | * \param value The string value of the tag 578 | * \returns The array of all found descendant nodes or an empty array 579 | */ 580 | - (NSArray *)descendantsOfTag:(NSString *)tagName valueMatches:(NSString *)value; 581 | 582 | /*! Returns all child nodes with the specifed tag name and string value matching exactly 583 | * \param tagName The name of the tag 584 | * \param value The string value of the tag 585 | * \returns The array of all found child nodes or an empty array 586 | */ 587 | - (NSArray *)childrenOfTag:(NSString *)tagName valueMatches:(NSString *)value; 588 | 589 | /*! Returns all sibling nodes with the specifed tag name and string value matching exactly 590 | * \param tagName The name of the tag 591 | * \param value The string value of the tag 592 | * \returns The array of all found sibling nodes or an empty array 593 | */ 594 | - (NSArray *)siblingsOfTag:(NSString *)tagName valueMatches:(NSString *)value; 595 | 596 | /*! Returns the first descendant node with the specifed attribute name and the string value contains the specified value 597 | * \param tagName The name of the attribute 598 | * \param value The partial string of the attribute value 599 | * \returns The first found descendant node or nil if no node matches the parameters 600 | */ 601 | - (nullable HTMLNode *)descendantOfTag:(NSString *)tagName valueContains:(NSString *)value; 602 | 603 | /*! Returns the child node with the specifed attribute name and the string value contains the specified value 604 | * \param tagName The name of the attribute 605 | * \param value The partial string of the attribute value 606 | * \returns The first found child node or nil if no node matches the parameters 607 | */ 608 | - (nullable HTMLNode *)childOfTag:(NSString *)tagName valueContains:(NSString *)value; 609 | 610 | /*! Returns the sibling node with the specifed attribute name and the string value contains the specified value 611 | * \param tagName The name of the attribute 612 | * \param value The partial string of the attribute value 613 | * \returns The first found sibling node or nil if no node matches the parameters 614 | */ 615 | - (nullable HTMLNode *)siblingOfTag:(NSString *)tagName valueContains:(NSString *)value; 616 | 617 | /*! Returns all descendant nodes with the specifed attribute name and the string value contains the specified value 618 | * \param tagName The name of the attribute 619 | * \param value The partial string of the attribute value 620 | * \returns The array of all found descendant nodes or an empty array 621 | */ 622 | - (NSArray *)descendantsOfTag:(NSString *)tagName valueContains:(NSString *)value; 623 | 624 | /*! Returns all child nodes with the specifed attribute name and the string value contains the specified value 625 | * \param tagName The name of the attribute 626 | * \param value The partial string of the attribute value 627 | * \returns The array of all found child nodes or an empty array 628 | */ 629 | - (NSArray *)childrenOfTag:(NSString *)tagName valueContains:(NSString *)value; 630 | 631 | /*! Returns all sibling nodes with the specifed attribute name and the string value contains the specified value 632 | * \param tagName The name of the attribute 633 | * \param value The partial string of the attribute value 634 | * \returns The array of all found sibling nodes or an empty array 635 | */ 636 | - (NSArray *)siblingsOfTag:(NSString *)tagName valueContains:(NSString *)value; 637 | 638 | /*! Returns the first descendant node with the specifed tag name 639 | * \param tagName The name of the tag 640 | * \returns The first found descendant node or nil 641 | */ 642 | - (nullable HTMLNode *)descendantOfTag:(NSString *)tagName; 643 | 644 | /*! Returns the first child node with the specifed tag name 645 | * \param tagName The name of the tag 646 | * \returns The first found child node or nil 647 | */ 648 | - (nullable HTMLNode *)childOfTag:(NSString *)tagName; 649 | 650 | /*! Returns the first sibling node with the specifed tag name 651 | * \param tagName The name of the tag 652 | * \returns The first found sibling node or nil 653 | */ 654 | - (nullable HTMLNode *)siblingOfTag:(NSString *)tagName; 655 | 656 | /*! Returns all descendant nodes with the specifed tag name 657 | * \param tagName The name of the tag 658 | * \returns The array of all found descendant nodes or an empty array 659 | */ 660 | - (NSArray *)descendantsOfTag:(NSString *)tagName; 661 | 662 | /*! Returns all child nodes with the specifed tag name 663 | * \param tagName The name of the tag 664 | * \returns The array of all found child nodes or an empty array 665 | */ 666 | 667 | - (NSArray *)childrenOfTag:(NSString *)tagName; 668 | 669 | /*! Returns all sibling nodes with the specifed tag name 670 | * \param tagName The name of the tag 671 | * \returns The array of all found sibling nodes or an empty array 672 | */ 673 | - (NSArray *)siblingsOfTag:(NSString *)tagName; 674 | 675 | NS_ASSUME_NONNULL_END 676 | 677 | @end 678 | --------------------------------------------------------------------------------