🎯 Рекомендуемые коллекции

Балансированные коллекции примеров кода из различных категорий, которые вы можете исследовать

Сериализация macOS Objective-C - Примеры

Примеры сериализации macOS Objective-C включая JSON-сериализацию, JSON-десериализацию и XML-парсинг

💻 JSON-сериализация objectivec

🟡 intermediate ⭐⭐⭐

Преобразование объектов Objective-C в JSON-строки с помощью NSJSONSerialization

⏱️ 25 min 🏷️ objectivec, macos, serialization, json
Prerequisites: Objective-C basics, Foundation framework
// macOS Objective-C JSON Serialization Examples
// Using NSJSONSerialization for JSON encoding

#import <Foundation/Foundation.h>

// MARK: - 1. Serialize Dictionary to JSON

@interface JSONSerializer : NSObject

+ (NSData *)serializeDictionaryToJSON:(NSDictionary *)dictionary;
+ (NSString *)serializeDictionaryToJSONString:(NSDictionary *)dictionary;
+ (BOOL)writeDictionaryToJSONFile:(NSDictionary *)dictionary path:(NSString *)path;

@end

@implementation JSONSerializer

+ (NSData *)serializeDictionaryToJSON:(NSDictionary *)dictionary {
    NSError *error = nil;

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
                                                       options:0 // NSJSONWritingOptions
                                                         error:&error];

    if (error) {
        NSLog(@"JSON serialization error: %@", error.localizedDescription);
        return nil;
    }

    NSLog(@"Dictionary serialized to JSON data (%lu bytes)", (unsigned long)jsonData.length);
    return jsonData;
}

+ (NSString *)serializeDictionaryToJSONString:(NSDictionary *)dictionary {
    NSData *jsonData = [self serializeDictionaryToJSON:dictionary];

    if (!jsonData) {
        return nil;
    }

    NSString *jsonString = [[NSString alloc] initWithData:jsonData
                                                  encoding:NSUTF8StringEncoding];

    NSLog(@"JSON String: %@", jsonString);
    return jsonString;
}

+ (BOOL)writeDictionaryToJSONFile:(NSDictionary *)dictionary path:(NSString *)path {
    NSError *error = nil;

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&error];

    if (error) {
        NSLog(@"JSON serialization error: %@", error.localizedDescription);
        return NO;
    }

    BOOL success = [jsonData writeToFile:path
                                 options:NSDataWritingAtomic
                                   error:&error];

    if (error) {
        NSLog(@"File write error: %@", error.localizedDescription);
        return NO;
    }

    NSLog(@"JSON written to file: %@", path);
    return success;
}

@end

// MARK: - 2. Serialize Array to JSON

@interface JSONArraySerializer : NSObject

+ (NSData *)serializeArrayToJSON:(NSArray *)array;
+ (NSString *)serializeArrayToJSONString:(NSArray *)array;
+ (NSData *)serializeArrayToPrettyJSON:(NSArray *)array;

@end

@implementation JSONArraySerializer

+ (NSData *)serializeArrayToJSON:(NSArray *)array {
    NSError *error = nil;

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array
                                                       options:0
                                                         error:&error];

    if (error) {
        NSLog(@"JSON serialization error: %@", error.localizedDescription);
        return nil;
    }

    NSLog(@"Array serialized to JSON data");
    return jsonData;
}

+ (NSString *)serializeArrayToJSONString:(NSArray *)array {
    NSData *jsonData = [self serializeArrayToJSON:array];

    if (!jsonData) {
        return nil;
    }

    NSString *jsonString = [[NSString alloc] initWithData:jsonData
                                                  encoding:NSUTF8StringEncoding];

    NSLog(@"JSON Array String: %@", jsonString);
    return jsonString;
}

+ (NSData *)serializeArrayToPrettyJSON:(NSArray *)array {
    NSError *error = nil;

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&error];

    if (error) {
        NSLog(@"JSON serialization error: %@", error.localizedDescription);
        return nil;
    }

    NSLog(@"Array serialized to pretty JSON");
    return jsonData;
}

@end

// MARK: - 3. Serialize Custom Object to JSON

@interface Person : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *email;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) NSArray *hobbies;

- (NSDictionary *)toDictionary;

@end

@implementation Person

- (NSDictionary *)toDictionary {
    return @{
        @"name": self.name ?: [NSNull null],
        @"email": self.email ?: [NSNull null],
        @"age": @(self.age),
        @"hobbies": self.hobbies ?: @[]
    };
}

@end

@interface CustomObjectSerializer : NSObject

+ (NSData *)serializePersonToJSON:(Person *)person;
+ (NSData *)serializePersonArrayToJSON:(NSArray *)people;

@end

@implementation CustomObjectSerializer

+ (NSData *)serializePersonToJSON:(Person *)person {
    NSDictionary *dict = [person toDictionary];

    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&error];

    if (error) {
        NSLog(@"JSON serialization error: %@", error.localizedDescription);
        return nil;
    }

    NSLog(@"Person serialized to JSON");
    return jsonData;
}

+ (NSData *)serializePersonArrayToJSON:(NSArray *)people {
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:people.count];

    for (Person *person in people) {
        [array addObject:[person toDictionary]];
    }

    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&error];

    if (error) {
        NSLog(@"JSON serialization error: %@", error.localizedDescription);
        return nil;
    }

    NSLog(@"Person array serialized to JSON");
    return jsonData;
}

@end

// MARK: - 4. Serialize Nested Objects

@interface Company : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *location;
@property (nonatomic, strong) NSArray *employees;

- (NSDictionary *)toDictionary;

@end

@implementation Company

- (NSDictionary *)toDictionary {
    NSMutableArray *employeeArray = [NSMutableArray array];

    for (Person *employee in self.employees) {
        [employeeArray addObject:[employee toDictionary]];
    }

    return @{
        @"name": self.name,
        @"location": self.location,
        @"employees": employeeArray
    };
}

@end

@interface NestedObjectSerializer : NSObject

+ (NSData *)serializeCompanyToJSON:(Company *)company;

@end

@implementation NestedObjectSerializer

+ (NSData *)serializeCompanyToJSON:(Company *)company {
    NSDictionary *dict = [company toDictionary];

    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&error];

    if (error) {
        NSLog(@"JSON serialization error: %@", error.localizedDescription);
        return nil;
    }

    NSLog(@"Company serialized to JSON");
    return jsonData;
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C JSON Serialization Examples ===\n");

        // 1. Serialize dictionary
        NSLog(@"--- 1. Serialize Dictionary ---");

        NSDictionary *userDict = @{
            @"id": @(1),
            @"username": @"john_doe",
            @"email": @"[email protected]",
            @"active": @(YES),
            @"balance": @(1234.56)
        };

        [JSONSerializer serializeDictionaryToJSONString:userDict];

        NSString *jsonPath = @"/tmp/user.json";
        [JSONSerializer writeDictionaryToJSONFile:userDict path:jsonPath];

        // 2. Serialize array
        NSLog(@"\n--- 2. Serialize Array ---");

        NSArray *fruits = @[@"Apple", @"Banana", @"Orange", @"Mango"];
        [JSONArraySerializer serializeArrayToJSONString:fruits];

        NSArray *numbers = @[@1, @2, @3, @4, @5];
        [JSONArraySerializer serializeArrayToJSONString:numbers];

        // 3. Serialize custom object
        NSLog(@"\n--- 3. Serialize Custom Object ---");

        Person *person = [[Person alloc] init];
        person.name = @"Alice Smith";
        person.email = @"[email protected]";
        person.age = 30;
        person.hobbies = @[@"Reading", @"Hiking", @"Photography"];

        NSData *personJSON = [CustomObjectSerializer serializePersonToJSON:person];
        if (personJSON) {
            NSString *jsonString = [[NSString alloc] initWithData:personJSON
                                                          encoding:NSUTF8StringEncoding];
            NSLog(@"Person JSON:\n%@", jsonString);
        }

        // 4. Serialize object array
        NSLog(@"\n--- 4. Serialize Object Array ---");

        Person *p1 = [[Person alloc] init];
        p1.name = @"Bob";
        p1.email = @"[email protected]";
        p1.age = 25;
        p1.hobbies = @[@"Gaming"];

        Person *p2 = [[Person alloc] init];
        p2.name = @"Charlie";
        p2.email = @"[email protected]";
        p2.age = 35;
        p2.hobbies = @[@"Cooking", @"Traveling"];

        NSArray *people = @[p1, p2];
        NSData *peopleJSON = [CustomObjectSerializer serializePersonArrayToJSON:people];
        if (peopleJSON) {
            NSString *jsonString = [[NSString alloc] initWithData:peopleJSON
                                                          encoding:NSUTF8StringEncoding];
            NSLog(@"People Array JSON:\n%@", jsonString);
        }

        // 5. Serialize nested objects
        NSLog(@"\n--- 5. Serialize Nested Objects ---");

        Company *company = [[Company alloc] init];
        company.name = @"Tech Corp";
        company.location = @"San Francisco, CA";

        Person *emp1 = [[Person alloc] init];
        emp1.name = @"David";
        emp1.email = @"[email protected]";
        emp1.age = 28;
        emp1.hobbies = @[@"Coding"];

        Person *emp2 = [[Person alloc] init];
        emp2.name = @"Emma";
        emp2.email = @"[email protected]";
        emp2.age = 32;
        emp2.hobbies = @[@"Design", @"Music"];

        company.employees = @[emp1, emp2];

        NSData *companyJSON = [NestedObjectSerializer serializeCompanyToJSON:company];
        if (companyJSON) {
            NSString *jsonString = [[NSString alloc] initWithData:companyJSON
                                                          encoding:NSUTF8StringEncoding];
            NSLog(@"Company JSON:\n%@", jsonString);
        }

        NSLog(@"\n=== JSON Serialization Examples Completed ===");
    }

    return 0;
}

💻 JSON-десериализация objectivec

🟡 intermediate ⭐⭐⭐

Анализ JSON-строк и преобразование в объекты Objective-C с помощью NSJSONSerialization

⏱️ 25 min 🏷️ objectivec, macos, serialization, json
Prerequisites: Objective-C basics, Foundation framework
// macOS Objective-C JSON Deserialization Examples
// Using NSJSONSerialization for JSON decoding

#import <Foundation/Foundation.h>

// MARK: - 1. Deserialize JSON to Dictionary

@interface JSONDeserializer : NSObject

+ (NSDictionary *)deserializeJSONToDictionary:(NSData *)jsonData;
+ (NSDictionary *)deserializeJSONStringToDictionary:(NSString *)jsonString;
+ (NSDictionary *)readJSONFileToDictionary:(NSString *)path;

@end

@implementation JSONDeserializer

+ (NSDictionary *)deserializeJSONToDictionary:(NSData *)jsonData {
    NSError *error = nil;

    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                    options:0
                                                      error:&error];

    if (error) {
        NSLog(@"JSON deserialization error: %@", error.localizedDescription);
        return nil;
    }

    if (![jsonObject isKindOfClass:[NSDictionary class]]) {
        NSLog(@"JSON is not a dictionary");
        return nil;
    }

    NSLog(@"JSON deserialized to dictionary");
    return (NSDictionary *)jsonObject;
}

+ (NSDictionary *)deserializeJSONStringToDictionary:(NSString *)jsonString {
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

    if (!jsonData) {
        NSLog(@"Failed to convert string to data");
        return nil;
    }

    return [self deserializeJSONToDictionary:jsonData];
}

+ (NSDictionary *)readJSONFileToDictionary:(NSString *)path {
    NSError *error = nil;

    NSData *jsonData = [NSData dataWithContentsOfFile:path
                                              options:0
                                                error:&error];

    if (error) {
        NSLog(@"File read error: %@", error.localizedDescription);
        return nil;
    }

    return [self deserializeJSONToDictionary:jsonData];
}

@end

// MARK: - 2. Deserialize JSON to Array

@interface JSONArrayDeserializer : NSObject

+ (NSArray *)deserializeJSONToArray:(NSData *)jsonData;
+ (NSArray *)deserializeJSONStringToArray:(NSString *)jsonString;

@end

@implementation JSONArrayDeserializer

+ (NSArray *)deserializeJSONToArray:(NSData *)jsonData {
    NSError *error = nil;

    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                    options:0
                                                      error:&error];

    if (error) {
        NSLog(@"JSON deserialization error: %@", error.localizedDescription);
        return nil;
    }

    if (![jsonObject isKindOfClass:[NSArray class]]) {
        NSLog(@"JSON is not an array");
        return nil;
    }

    NSLog(@"JSON deserialized to array");
    return (NSArray *)jsonObject;
}

+ (NSArray *)deserializeJSONStringToArray:(NSString *)jsonString {
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

    if (!jsonData) {
        NSLog(@"Failed to convert string to data");
        return nil;
    }

    return [self deserializeJSONToArray:jsonData];
}

@end

// MARK: - 3. Deserialize to Custom Object

@interface Person : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *email;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) NSArray *hobbies;

+ (instancetype)fromDictionary:(NSDictionary *)dict;
- (NSString *)description;

@end

@implementation Person

+ (instancetype)fromDictionary:(NSDictionary *)dict {
    Person *person = [[Person alloc] init];

    person.name = dict[@"name"];
    person.email = dict[@"email"];

    id ageValue = dict[@"age"];
    if ([ageValue isKindOfClass:[NSNumber class]]) {
        person.age = [ageValue integerValue];
    }

    id hobbiesValue = dict[@"hobbies"];
    if ([hobbiesValue isKindOfClass:[NSArray class]]) {
        person.hobbies = (NSArray *)hobbiesValue;
    } else {
        person.hobbies = @[];
    }

    return person;
}

- (NSString *)description {
    return [NSString stringWithFormat:@"Person[name=%@, email=%@, age=%ld, hobbies=%@]",
            self.name, self.email, (long)self.age, self.hobbies];
}

@end

@interface CustomObjectDeserializer : NSObject

+ (Person *)deserializePersonFromJSON:(NSData *)jsonData;
+ (NSArray *)deserializePersonArrayFromJSON:(NSData *)jsonData;

@end

@implementation CustomObjectDeserializer

+ (Person *)deserializePersonFromJSON:(NSData *)jsonData {
    NSError *error = nil;

    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                    options:0
                                                      error:&error];

    if (error) {
        NSLog(@"JSON deserialization error: %@", error.localizedDescription);
        return nil;
    }

    if (![jsonObject isKindOfClass:[NSDictionary class]]) {
        NSLog(@"JSON is not a dictionary");
        return nil;
    }

    Person *person = [Person fromDictionary:(NSDictionary *)jsonObject];
    NSLog(@"Person deserialized from JSON");

    return person;
}

+ (NSArray *)deserializePersonArrayFromJSON:(NSData *)jsonData {
    NSError *error = nil;

    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                    options:0
                                                      error:&error];

    if (error) {
        NSLog(@"JSON deserialization error: %@", error.localizedDescription);
        return nil;
    }

    if (![jsonObject isKindOfClass:[NSArray class]]) {
        NSLog(@"JSON is not an array");
        return nil;
    }

    NSArray *jsonArray = (NSArray *)jsonObject;
    NSMutableArray *people = [NSMutableArray arrayWithCapacity:jsonArray.count];

    for (NSDictionary *dict in jsonArray) {
        if ([dict isKindOfClass:[NSDictionary class]]) {
            [people addObject:[Person fromDictionary:dict]];
        }
    }

    NSLog(@"Person array deserialized from JSON (%lu people)", (unsigned long)people.count);
    return [people copy];
}

@end

// MARK: - 4. Handle Invalid JSON

@interface JSONValidator : NSObject

+ (BOOL)isValidJSON:(NSData *)jsonData;
+ (NSString *)getValidationError:(NSData *)jsonData;

@end

@implementation JSONValidator

+ (BOOL)isValidJSON:(NSData *)jsonData {
    NSError *error = nil;

    [NSJSONSerialization JSONObjectWithData:jsonData
                                    options:0
                                      error:&error];

    return error == nil;
}

+ (NSString *)getValidationError:(NSData *)jsonData {
    NSError *error = nil;

    [NSJSONSerialization JSONObjectWithData:jsonData
                                    options:0
                                      error:&error];

    return error ? error.localizedDescription : nil;
}

@end

// MARK: - 5. Parse Mixed JSON Structures

@interface MixedJSONParser : NSObject

+ (void)parseMixedJSON:(NSData *)jsonData;

@end

@implementation MixedJSONParser

+ (void)parseMixedJSON:(NSData *)jsonData {
    NSError *error = nil;

    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                    options:0
                                                      error:&error];

    if (error) {
        NSLog(@"JSON parsing error: %@", error.localizedDescription);
        return;
    }

    if ([jsonObject isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dict = (NSDictionary *)jsonObject;
        NSLog(@"Parsed dictionary with %lu keys", (unsigned long)dict.count);

        // Iterate through dictionary
        [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
            NSLog(@"  Key: %@, Value: %@", key, obj);

            if ([obj isKindOfClass:[NSArray class]]) {
                NSLog(@"    -> Array with %lu items", (unsigned long)[obj count]);
            } else if ([obj isKindOfClass:[NSDictionary class]]) {
                NSLog(@"    -> Nested dictionary");
            }
        }];

    } else if ([jsonObject isKindOfClass:[NSArray class]]) {
        NSArray *array = (NSArray *)jsonObject;
        NSLog(@"Parsed array with %lu items", (unsigned long)array.count);
    }
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C JSON Deserialization Examples ===\n");

        // 1. Deserialize to dictionary
        NSLog(@"--- 1. Deserialize to Dictionary ---");

        NSString *userJSONString = @"{\"id\": 1,\"username\": \"john_doe\", \"email\": \"[email protected]\", \"active\": true}";

        NSDictionary *userDict = [JSONDeserializer deserializeJSONStringToDictionary:userJSONString];
        if (userDict) {
            NSLog(@"Username: %@", userDict[@"username"]);
            NSLog(@"Email: %@", userDict[@"email"]);
            NSLog(@"Active: %@", userDict[@"active"]);
        }

        // 2. Deserialize to array
        NSLog(@"\n--- 2. Deserialize to Array ---");

        NSString *fruitsJSONString = @"[\"Apple\", \"Banana\", \"Orange\", \"Mango\"]";

        NSArray *fruits = [JSONArrayDeserializer deserializeJSONStringToArray:fruitsJSONString];
        if (fruits) {
            NSLog(@"Fruits: %@", fruits);
        }

        // 3. Deserialize to custom object
        NSLog(@"\n--- 3. Deserialize to Custom Object ---");

        NSString *personJSONString = @"{\"name\": \"Alice Smith\", \"email\": \"[email protected]\", \"age\": 30, \"hobbies\": [\"Reading\", \"Hiking\"]}";

        NSData *personJSONData = [personJSONString dataUsingEncoding:NSUTF8StringEncoding];
        Person *person = [CustomObjectDeserializer deserializePersonFromJSON:personJSONData];
        if (person) {
            NSLog(@"%@", person);
        }

        // 4. Deserialize to object array
        NSLog(@"\n--- 4. Deserialize to Object Array ---");

        NSString *peopleJSONString = @"["
            @"{\"name\": \"Bob\", \"email\": \"[email protected]\", \"age\": 25, \"hobbies\": [\"Gaming\"]},"
            @"{\"name\": \"Charlie\", \"email\": \"[email protected]\", \"age\": 35, \"hobbies\": [\"Cooking\", \"Traveling\"]}"
        @"]";

        NSData *peopleJSONData = [peopleJSONString dataUsingEncoding:NSUTF8StringEncoding];
        NSArray *people = [CustomObjectDeserializer deserializePersonArrayFromJSON:peopleJSONData];
        for (Person *p in people) {
            NSLog(@"%@", p);
        }

        // 5. Validate JSON
        NSLog(@"\n--- 5. Validate JSON ---");

        NSString *validJSON = @"{\"name\": \"Test\", \"value\": 123}";
        NSString *invalidJSON = @"{\"name\": \"Test\, \"value\": 123}";

        NSData *validData = [validJSON dataUsingEncoding:NSUTF8StringEncoding];
        NSData *invalidData = [invalidJSON dataUsingEncoding:NSUTF8StringEncoding];

        NSLog(@"Valid JSON: %d", [JSONValidator isValidJSON:validData]);
        NSLog(@"Invalid JSON: %d", [JSONValidator isValidJSON:invalidData]);

        NSString *error = [JSONValidator getValidationError:invalidData];
        if (error) {
            NSLog(@"Error: %@", error);
        }

        // 6. Parse mixed structures
        NSLog(@"\n--- 6. Parse Mixed Structures ---");

        NSString *mixedJSON = @"{"
            @"\"company\": \"Tech Corp\","
            @"\"employees\": ["
            @"  {\"name\": \"Alice\", \"role\": \"Engineer\"},"
            @"  {\"name\": \"Bob\", \"role\": \"Designer\"}"
            @"],"
            @"\"metadata\": {"
            @"   \"founded\": 2010,"
            @"   \"location\": \"San Francisco\""
            @"}"
        @"}";

        NSData *mixedData = [mixedJSON dataUsingEncoding:NSUTF8StringEncoding];
        [MixedJSONParser parseMixedJSON:mixedData];

        NSLog(@"\n=== JSON Deserialization Examples Completed ===");
    }

    return 0;
}

💻 XML-парсинг objectivec

🟡 intermediate ⭐⭐⭐

Анализ XML-документов с помощью NSXMLParser с паттерном делегата

⏱️ 30 min 🏷️ objectivec, macos, serialization, xml
Prerequisites: Objective-C basics, Foundation framework, Delegate pattern
// macOS Objective-C XML Parsing Examples
// Using NSXMLParser delegate pattern

#import <Foundation/Foundation.h>

// MARK: - 1. Simple XML Parser

@interface SimpleXMLParser : NSObject <NSXMLParserDelegate>

@property (nonatomic, strong) NSMutableString *currentElementValue;
@property (nonatomic, strong) NSMutableArray *parsedItems;
@property (nonatomic, strong) NSMutableDictionary *currentItem;

- (void)parseXMLFromString:(NSString *)xmlString;
- (void)parseXMLFromFile:(NSString *)filePath;

@end

@implementation SimpleXMLParser

- (instancetype)init {
    self = [super init];

    if (self) {
        _currentElementValue = [[NSMutableString alloc] init];
        _parsedItems = [[NSMutableArray alloc] init];
    }

    return self;
}

- (void)parseXMLFromString:(NSString *)xmlString {
    NSData *xmlData = [xmlString dataUsingEncoding:NSUTF8StringEncoding];

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
    parser.delegate = self;

    BOOL success = [parser parse];

    if (success) {
        NSLog(@"XML parsing successful, parsed %lu items", (unsigned long)self.parsedItems.count);
    } else {
        NSLog(@"XML parsing failed: %@", parser.parserError.localizedDescription);
    }
}

- (void)parseXMLFromFile:(NSString *)filePath {
    NSData *xmlData = [NSData dataWithContentsOfFile:filePath];

    if (!xmlData) {
        NSLog(@"Failed to read XML file");
        return;
    }

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
    parser.delegate = self;

    BOOL success = [parser parse];

    if (success) {
        NSLog(@"XML parsing successful, parsed %lu items", (unsigned long)self.parsedItems.count);
    } else {
        NSLog(@"XML parsing failed: %@", parser.parserError.localizedDescription);
    }
}

// NSXMLParserDelegate methods

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName
    attributes:(NSDictionary<NSString *, NSString *> *)attributeDict {

    [self.currentElementValue setString:@""];

    if ([elementName isEqualToString:@"item"]) {
        self.currentItem = [[NSMutableDictionary alloc] init];
    }

    NSLog(@"Started element: %@", elementName);

    // Log attributes
    [attributeDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
        NSLog(@"  Attribute: %@ = %@", key, value);
    }];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [self.currentElementValue appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName {

    NSString *trimmedValue = [self.currentElementValue stringByTrimmingCharactersInSet:
                             [NSCharacterSet whitespaceAndNewlineCharacterSet]];

    if ([elementName isEqualToString:@"item"]) {
        if (self.currentItem) {
            [self.parsedItems addObject:self.currentItem];
            self.currentItem = nil;
        }
    } else if (self.currentItem && trimmedValue.length > 0) {
        [self.currentItem setObject:trimmedValue forKey:elementName];
    }

    NSLog(@"Ended element: %@ = %@", elementName, trimmedValue);
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
    NSLog(@"XML document parsing completed");
    NSLog(@"Parsed items: %@", self.parsedItems);
}

@end

// MARK: - 2. Catalog XML Parser

@interface Book : NSObject

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *author;
@property (nonatomic, strong) NSString *genre;
@property (nonatomic, assign) CGFloat price;
@property (nonatomic, assign) NSInteger publishDate;
@property (nonatomic, strong) NSString *description;

- (NSString *)description;

@end

@implementation Book

- (NSString *)description {
    return [NSString stringWithFormat:@"Book[title=%@, author=%@, genre=%@, price=%.2f, year=%ld]",
            self.title, self.author, self.genre, self.price, (long)self.publishDate];
}

@end

@interface CatalogXMLParser : NSObject <NSXMLParserDelegate>

@property (nonatomic, strong) NSMutableArray *books;
@property (nonatomic, strong) Book *currentBook;
@property (nonatomic, strong) NSMutableString *currentText;

- (NSArray *)parseCatalogXML:(NSString *)xmlString;

@end

@implementation CatalogXMLParser

- (instancetype)init {
    self = [super init];

    if (self) {
        _books = [[NSMutableArray alloc] init];
        _currentText = [[NSMutableString alloc] init];
    }

    return self;
}

- (NSArray *)parseCatalogXML:(NSString *)xmlString {
    NSData *xmlData = [xmlString dataUsingEncoding:NSUTF8StringEncoding];

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
    parser.delegate = self;

    if ([parser parse]) {
        NSLog(@"Catalog parsed successfully, %lu books", (unsigned long)self.books.count);
        return [self.books copy];
    }

    NSLog(@"Parsing failed: %@", parser.parserError.localizedDescription);
    return nil;
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName
    attributes:(NSDictionary *)attributeDict {

    [self.currentText setString:@""];

    if ([elementName isEqualToString:@"book"]) {
        self.currentBook = [[Book alloc] init];

        // Extract attributes from book element
        NSString *idValue = attributeDict[@"id"];
        NSLog(@"Parsing book with ID: %@", idValue);
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [self.currentText appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName {

    NSString *trimmedText = [self.currentText stringByTrimmingCharactersInSet:
                            [NSCharacterSet whitespaceAndNewlineCharacterSet]];

    if ([elementName isEqualToString:@"book"]) {
        if (self.currentBook) {
            [self.books addObject:self.currentBook];
            self.currentBook = nil;
        }
    } else if (self.currentBook) {
        if ([elementName isEqualToString:@"title"]) {
            self.currentBook.title = trimmedText;
        } else if ([elementName isEqualToString:@"author"]) {
            self.currentBook.author = trimmedText;
        } else if ([elementName isEqualToString:@"genre"]) {
            self.currentBook.genre = trimmedText;
        } else if ([elementName isEqualToString:@"price"]) {
            self.currentBook.price = [trimmedText floatValue];
        } else if ([elementName isEqualToString:@"publish_date"]) {
            // Parse year from date format
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            formatter.dateFormat = @"yyyy-MM-dd";
            NSDate *date = [formatter dateFromString:trimmedText];

            if (date) {
                NSCalendar *calendar = [NSCalendar currentCalendar];
                NSDateComponents *components = [calendar components:NSCalendarUnitYear
                                                            fromDate:date];
                self.currentBook.publishDate = components.year;
            }
        } else if ([elementName isEqualToString:@"description"]) {
            self.currentBook.description = trimmedText;
        }
    }
}

@end

// MARK: - 3. RSS Feed Parser

@interface RSSFeedParser : NSObject <NSXMLParserDelegate>

@property (nonatomic, strong) NSMutableArray *items;
@property (nonatomic, strong) NSMutableDictionary *currentItem;
@property (nonatomic, strong) NSMutableString *currentElementValue;
@property (nonatomic, strong) NSMutableString *currentElementName;

@property (nonatomic, strong) NSString *feedTitle;
@property (nonatomic, strong) NSString *feedDescription;
@property (nonatomic, strong) NSString *feedLink;

- (NSDictionary *)parseRSSFeed:(NSString *)rssString;

@end

@implementation RSSFeedParser

- (instancetype)init {
    self = [super init];

    if (self) {
        _items = [[NSMutableArray alloc] init];
        _currentElementValue = [[NSMutableString alloc] init];
        _currentElementName = [[NSMutableString alloc] init];
    }

    return self;
}

- (NSDictionary *)parseRSSFeed:(NSString *)rssString {
    NSData *rssData = [rssString dataUsingEncoding:NSUTF8StringEncoding];

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:rssData];
    parser.delegate = self;

    if ([parser parse]) {
        NSLog(@"RSS feed parsed, %lu items", (unsigned long)self.items.count);

        return @{
            @"title": self.feedTitle ?: @"",
            @"description": self.feedDescription ?: @"",
            @"link": self.feedLink ?: @"",
            @"items": [self.items copy]
        };
    }

    return nil;
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName
    attributes:(NSDictionary *)attributeDict {

    [self.currentElementName setString:elementName];
    [self.currentElementValue setString:@""];

    if ([elementName isEqualToString:@"item"]) {
        self.currentItem = [[NSMutableDictionary alloc] init];
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [self.currentElementValue appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName {

    NSString *value = [self.currentElementValue stringByTrimmingCharactersInSet:
                      [NSCharacterSet whitespaceAndNewlineCharacterSet]];

    if ([elementName isEqualToString:@"item"]) {
        if (self.currentItem) {
            [self.items addObject:self.currentItem];
            self.currentItem = nil;
        }
    } else if ([elementName isEqualToString:@"title"] && !self.currentItem) {
        self.feedTitle = value;
    } else if ([elementName isEqualToString:@"description"] && !self.currentItem) {
        self.feedDescription = value;
    } else if ([elementName isEqualToString:@"link"] && !self.currentItem) {
        self.feedLink = value;
    } else if (self.currentItem && value.length > 0) {
        [self.currentItem setObject:value forKey:elementName];
    }
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C XML Parsing Examples ===\n");

        // 1. Simple XML parsing
        NSLog(@"--- 1. Simple XML Parsing ---");

        NSString *simpleXML = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            @"<data>"
            @"  <item>"
            @"    <name>Apple</name>"
            @"    <price>1.50</price>"
            @"    <quantity>10</quantity>"
            @"  </item>"
            @"  <item>"
            @"    <name>Banana</name>"
            @"    <price>0.75</price>"
            @"    <quantity>20</quantity>"
            @"  </item>"
            @"</data>";

        SimpleXMLParser *simpleParser = [[SimpleXMLParser alloc] init];
        [simpleParser parseXMLFromString:simpleXML];

        // 2. Catalog XML parsing
        NSLog(@"\n--- 2. Catalog XML Parsing ---");

        NSString *catalogXML = @"<?xml version=\"1.0\"?>"
            @"<catalog>"
            @"  <book id=\"bk101\">"
            @"    <author>Gambardella, Matthew</author>"
            @"    <title>XML Developer's Guide</title>"
            @"    <genre>Computer</genre>"
            @"    <price>44.95</price>"
            @"    <publish_date>2000-10-01</publish_date>"
            @"    <description>An in-depth look at creating applications with XML.</description>"
            @"  </book>"
            @"  <book id=\"bk102\">"
            @"    <author>Ralls, Kim</author>"
            @"    <title>Midnight Rain</title>"
            @"    <genre>Fantasy</genre>"
            @"    <price>5.95</price>"
            @"    <publish_date>2000-12-16</publish_date>"
            @"    <description>A former architect battles corporate zombies.</description>"
            @"  </book>"
            @"</catalog>";

        CatalogXMLParser *catalogParser = [[CatalogXMLParser alloc] init];
        NSArray *books = [catalogParser parseCatalogXML:catalogXML];

        for (Book *book in books) {
            NSLog(@"%@", book);
        }

        // 3. RSS feed parsing
        NSLog(@"\n--- 3. RSS Feed Parsing ---");

        NSString *rssFeed = @"<?xml version=\"1.0\"?>"
            @"<rss version=\"2.0\">"
            @"  <channel>"
            @"    <title>Tech News</title>"
            @"    <description>Latest technology news</description>"
            @"    <link>https://example.com</link>"
            @"    <item>"
            @"      <title>New iPhone Released</title>"
            @"      <link>https://example.com/iphone</link>"
            @"      <description>Apple announces latest iPhone model</description>"
            @"      <pubDate>Mon, 25 Dec 2025 10:00:00 GMT</pubDate>"
            @"    </item>"
            @"    <item>"
            @"      <title>AI Breakthrough</title>"
            @"      <link>https://example.com/ai</link>"
            @"      <description>Scientists achieve major AI milestone</description>"
            @"      <pubDate>Sun, 24 Dec 2025 15:30:00 GMT</pubDate>"
            @"    </item>"
            @"  </channel>"
            @"</rss>";

        RSSFeedParser *rssParser = [[RSSFeedParser alloc] init];
        NSDictionary *feed = [rssParser parseRSSFeed:rssFeed];

        NSLog(@"Feed Title: %@", feed[@"title"]);
        NSLog(@"Feed Description: %@", feed[@"description"]);
        NSLog(@"\nFeed Items:");

        for (NSDictionary *item in feed[@"items"]) {
            NSLog(@"  - %@ (%@)", item[@"title"], item[@"pubDate"]);
        }

        NSLog(@"\n=== XML Parsing Examples Completed ===");
    }

    return 0;
}