vendoo_v1.0/Pods/PicoKit/Pod/Core/PicoXMLWriter.m
Okechi Onyeje 031a354996 Ebay Listing Now Posts both information and single image
need to rework on categories since subcategory workflow added some complications, but that will be taken care of in a bug fix task
2016-08-23 13:48:34 -04:00

257 lines
9.2 KiB
Objective-C

//
// PicoXMLWriter.m
// pico
//
// Created by bulldog on 13-2-26.
// Copyright (c) 2013 LeanSoft Technology. All rights reserved.
//
#import "PicoXMLWriter.h"
#import "PicoConverter.h"
#import "XMLWriter.h"
#import "PicoConfig.h"
#import "PicoBindingSchema.h"
#import "PicoClassSchema.h"
#import "PicoPropertySchema.h"
#import "PicoConstants.h"
#import "PicoXMLElement.h"
#import "PicoBindable.h"
@implementation PicoXMLWriter
@synthesize config = _config;
- (instancetype)init {
return [self initWithConfig:[[PicoConfig alloc] init]];
}
- (instancetype)initWithConfig:(PicoConfig *)config {
self = [super init];
if (self) {
self.config = config;
}
return self;
}
-(NSData *)toData:(id)obj {
NSString *xmlString = [self toString:obj] ;
NSData *data = [xmlString dataUsingEncoding: CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)self.config.encoding)) allowLossyConversion:NO];
return data;
}
-(NSString *)toString:(id)obj {
if (obj == nil) {
@throw [NSException exceptionWithName:@"WriterException" reason:@"Can't write nil object." userInfo:nil];
}
XMLWriter *xmlWriter = [[XMLWriter alloc] init];
_autoPrefixCount = 0;
[xmlWriter writeStartDocumentWithEncodingAndVersion:self.config.encoding version:@"1.0"];
PicoBindingSchema *bindingSchema = [PicoBindingSchema fromObject:obj];
PicoClassSchema *classSchema = [bindingSchema classSchema];
NSString *xmlName = classSchema.xmlName;
NSString *namespace = classSchema.nsURI;
if (!xmlName) { // workaround, in case xml name is not provided in class schema, use class name instead
xmlName = bindingSchema.className;
}
if ([namespace length] != 0) {
[xmlWriter setDefaultNamespace:namespace]; // bind to default namespace
}
[xmlWriter writeStartElementWithNamespace:namespace localName:xmlName];
[self writeObject:xmlWriter source:obj];
[xmlWriter writeEndElementWithNamespace:namespace localName:xmlName];
[xmlWriter writeEndDocument];
NSString *xmlString = [xmlWriter toString];
xmlString = [NSMutableString stringWithString:xmlString];
return xmlString;
}
-(void)writeObject:(XMLWriter *)xmlWriter source:(id)source {
PicoBindingSchema *bindingSchema = [PicoBindingSchema fromObject:source];
NSString *namespace = nil;
PicoClassSchema *classSchema = [bindingSchema classSchema];
if (classSchema) {
namespace = classSchema.nsURI;
}
[self writeAttributes:xmlWriter source:source schema:bindingSchema];
[self writeValue:xmlWriter source:source schema:bindingSchema];
// automatic prefixing
if (namespace && ![xmlWriter getPrefix:namespace]) {
NSString *prefix = [NSString stringWithFormat:@"ns%d", _autoPrefixCount++];
[xmlWriter setPrefix:prefix namespaceURI:namespace];
}
[self writeElements:xmlWriter source:source schema:bindingSchema namespace:namespace];
[self writeAnyElements:xmlWriter source:source schema:bindingSchema];
}
-(void)writeAttributes:(XMLWriter *)xmlWriter source:(id)source schema:(PicoBindingSchema *)bindingSchema {
NSDictionary *map = bindingSchema.property2AttributeSchemaMapping;
if (map.count > 0) {
for(NSString *propertyName in map) {
PicoPropertySchema *ps = map[propertyName];
id propertyValue = [source valueForKey:propertyName];
if (propertyValue) {
NSString *xmlString = [PicoConverter write:propertyValue withType:ps.propertyType config:self.config];
if (xmlString.length > 0) {
[xmlWriter writeAttribute:ps.xmlName value:xmlString];
}
}
}
}
}
-(void)writeValue:(XMLWriter *)xmlWriter source:(id)source schema:(PicoBindingSchema *)bindingSchema {
PicoPropertySchema *valuePs = bindingSchema.valueSchema;
if (valuePs) {
id propertyValue = [source valueForKey:valuePs.propertyName];
NSString *xmlString = [PicoConverter write:propertyValue withType:valuePs.propertyType config:self.config];
if (xmlString.length > 0) {
[xmlWriter writeCharacters:xmlString];
}
}
}
-(void)writeAnyElements:(XMLWriter *)xmlWriter source:(id)source schema:(PicoBindingSchema *)bindingSchema {
PicoPropertySchema *anyPs = bindingSchema.anyElementSchema;
if(anyPs) {
NSArray *anyArray = [source valueForKey: anyPs.propertyName];
if (anyArray) {
for(id entry in anyArray) {
if (entry) {
if ([entry isMemberOfClass:[PicoXMLElement class]]) {
[self writePicoXMLElement:xmlWriter xmlElement:entry];
} else if ([entry conformsToProtocol:@protocol(PicoBindable)]) {
[self writePicoObject:xmlWriter source:entry];
}
}
}
}
}
}
-(void)writePicoXMLElement:(XMLWriter *)xmlWriter xmlElement:(PicoXMLElement *)element {
if (!element) return; // to be cautious
if (element.name) {
NSString *namespace = element.nsUri;
if (namespace.length == 0) {
namespace = nil;
}
// automatic prefixing
if (namespace && ![xmlWriter getPrefix:namespace]) {
NSString *prefix = [NSString stringWithFormat:@"ns%d", _autoPrefixCount++];
[xmlWriter setPrefix:prefix namespaceURI:namespace];
}
[xmlWriter writeStartElementWithNamespace:namespace localName:element.name];
if (element.attributes) { // write attributes
for(NSString *key in element.attributes) {
NSString *value = [element.attributes valueForKey:key];
[xmlWriter writeAttribute:key value:value];
}
}
if (element.value) { // write element text
[xmlWriter writeCharacters:element.value];
}
if (element.children) { // write element children
for(PicoXMLElement *child in element.children) {
[self writePicoXMLElement:xmlWriter xmlElement:child];
}
}
[xmlWriter writeEndElementWithNamespace:namespace localName:element.name];
}
}
-(void)writePicoObject:(XMLWriter *)xmlWriter source:(id)source {
if (!source) return; // to be cautious
PicoBindingSchema *bindingSchema = [PicoBindingSchema fromObject:source];
PicoClassSchema *classSchema = [bindingSchema classSchema];
NSString *xmlName = classSchema.xmlName;
NSString *namespace = classSchema.nsURI;
if (!xmlName) { // workaround, in case xml name is not provided in class schema, use class name instead
xmlName = bindingSchema.className;
}
// automatic prefixing
if (namespace && ![xmlWriter getPrefix:namespace]) {
NSString *prefix = [NSString stringWithFormat:@"ns%d", _autoPrefixCount++];
[xmlWriter setPrefix:prefix namespaceURI:namespace];
}
[xmlWriter writeStartElementWithNamespace:namespace localName:xmlName];
[self writeObject:xmlWriter source:source];
[xmlWriter writeEndElementWithNamespace:namespace localName:xmlName];
}
-(void)writeElements:(XMLWriter *)xmlWriter source:(id)source schema:(PicoBindingSchema *)bindingSchema namespace:(NSString *)nsURI {
NSDictionary *map = bindingSchema.property2ElementSchemaMapping;
if (map.count > 0) {
for(NSString *propertyName in map) {
PicoPropertySchema *ps = map[propertyName];
id propertyValue = [source valueForKey:propertyName];
if (propertyValue) {
if ([ps.propertyKind isEqualToString:PICO_KIND_ELEMENT]) {
[self writeElement:xmlWriter source:propertyValue schema:ps namespace:nsURI];
}
// array elements
else if ([ps.propertyKind isEqualToString:PICO_KIND_ELEMENT_ARRAY]) {
NSArray *array = propertyValue;
for(id entry in array) {
if (entry) {
[self writeElement:xmlWriter source:entry schema:ps namespace:nsURI];
}
}
}
}
}
}
}
-(void)writeElement:(XMLWriter *)xmlWriter source:(id)source schema:(PicoPropertySchema *)propertySchema namespace:(NSString *)nsURI {
if (!source) return;
if ([PicoConverter isPrimitive:propertySchema.propertyType]) {
NSString *xmlString = [PicoConverter write:source withType:propertySchema.propertyType config:self.config];
if (xmlString.length > 0) {
[xmlWriter writeStartElementWithNamespace:nsURI localName:propertySchema.xmlName];
[xmlWriter writeCharacters:xmlString];
[xmlWriter writeEndElementWithNamespace:nsURI localName:propertySchema.xmlName];
}
return;
}
if ([propertySchema.propertyType isEqualToString:PICO_TYPE_OBJECT]) {
[xmlWriter writeStartElementWithNamespace:nsURI localName:propertySchema.xmlName];
[self writeObject:xmlWriter source:source];
[xmlWriter writeEndElementWithNamespace:nsURI localName:propertySchema.xmlName];
}
}
@end