1/************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24#import "OOoMetaDataParser.h" 25 26static NSSet *singleValueXMLElements; 27static NSSet *multiValueXMLElements; 28static NSDictionary *metaXML2MDIKeys; 29 30@implementation OOoMetaDataParser 31 32+ (void)initialize 33{ 34 static BOOL isInitialized = NO; 35 36 if (isInitialized == NO) { 37 //set up the meta elements with only one value 38 NSMutableSet *temp = [NSMutableSet new]; 39 [temp addObject:@"dc:title"]; 40 [temp addObject:@"dc:description"]; 41 [temp addObject:@"meta:user-defined"]; 42 singleValueXMLElements = [[NSSet setWithSet:temp] retain]; 43 44 //set up the meta elements that can have more than one value 45 [temp removeAllObjects]; 46 [temp addObject:@"dc:subject"]; 47 [temp addObject:@"meta:keyword"]; 48 [temp addObject:@"meta:initial-creator"]; 49 [temp addObject:@"dc:creator"]; 50 multiValueXMLElements = [[NSSet setWithSet:temp] retain]; 51 [temp release]; 52 53 //set up the map to store the values with the correct MDI keys 54 NSMutableDictionary *tempDict = [NSMutableDictionary new]; 55 [tempDict setObject:(NSString*)kMDItemTitle forKey:@"dc:title"]; 56 [tempDict setObject:(NSString*)kMDItemDescription forKey:@"dc:description"]; 57 [tempDict setObject:(NSString*)kMDItemKeywords forKey:@"dc:subject"]; 58 [tempDict setObject:(NSString*)kMDItemAuthors forKey:@"meta:initial-creator"]; 59 [tempDict setObject:(NSString*)kMDItemAuthors forKey:@"dc:creator"]; 60 [tempDict setObject:(NSString*)kMDItemKeywords forKey:@"meta:keyword"]; 61 [tempDict setObject:@"org_openoffice_opendocument_custominfo1" forKey:@"Info 1"]; 62 [tempDict setObject:@"org_openoffice_opendocument_custominfo2" forKey:@"Info 2"]; 63 [tempDict setObject:@"org_openoffice_opendocument_custominfo3" forKey:@"Info 3"]; 64 [tempDict setObject:@"org_openoffice_opendocument_custominfo4" forKey:@"Info 4"]; 65 metaXML2MDIKeys = [[NSDictionary dictionaryWithDictionary:tempDict] retain]; 66 [tempDict release]; 67 68 isInitialized = YES; 69 } 70} 71 72- (id)init 73{ 74 if ((self = [super init]) != nil) { 75 shouldReadCharacters = NO; 76// currentElement = nil; 77 textCurrentElement = nil; 78 79 return self; 80 } 81 82 return nil; 83} 84 85- (void)parseXML:(NSData*)data intoDictionary:(NSMutableDictionary*)dict 86{ 87 metaValues = dict; 88 89 //NSLog(@"data: %@ %d", data, [data length]); 90 91 //init parser settings 92 shouldReadCharacters = NO; 93 94 NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; 95 96 [parser setDelegate:self]; 97 [parser setShouldResolveExternalEntities:NO]; 98 [parser parse]; 99 100 [parser release]; 101 102 //NSLog(@"finished parsing meta"); 103} 104 105- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict 106{ 107// NSLog(@"<%@>", elementName); 108 if ([singleValueXMLElements containsObject:elementName] == YES) { 109 shouldReadCharacters = YES; 110 } else if ([multiValueXMLElements containsObject:elementName] == YES) { 111 shouldReadCharacters = YES; 112 } else { 113 //we are not interested in this element 114 shouldReadCharacters = NO; 115 return; 116 } 117 118 if (shouldReadCharacters == YES) { 119 textCurrentElement = [NSMutableString new]; 120 isCustom = [elementName isEqualToString:@"meta:user-defined"]; 121 if (isCustom == YES) { 122 customAttribute = [[attributeDict objectForKey:@"meta:name"] retain]; 123 //NSLog(customAttribute); 124 } 125 } 126 127 //NSLog(@"start element %@", elementName); 128} 129 130- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 131{ 132// NSLog(@"</%@>", elementName); 133 if (shouldReadCharacters == YES) { 134 NSString *mdiName = nil; 135 if (isCustom == YES) { 136 mdiName = (NSString*)[metaXML2MDIKeys objectForKey:customAttribute]; 137 } else { 138 mdiName = (NSString*)[metaXML2MDIKeys objectForKey:elementName]; 139 } 140 //NSLog(@"mdiName: %@", mdiName); 141 142 if (mdiName == nil) { 143 return; 144 } 145 146 if ([singleValueXMLElements containsObject:elementName] == YES) { 147 [metaValues setObject:textCurrentElement forKey:mdiName]; 148 } else { 149 // must be multi-value 150 NSMutableArray *arr = [metaValues objectForKey:mdiName]; 151 if (arr == nil) { 152 // we have no array yet, create it 153 arr = [[NSMutableArray new] autorelease]; 154 // and store it 155 [metaValues setObject:arr forKey:mdiName]; 156 } 157 // only store an element once, no need for duplicates 158 if ([arr containsObject:textCurrentElement] == NO) { 159 [arr addObject:textCurrentElement]; 160 } 161 } 162 // cleanup part 1 163 [textCurrentElement release]; 164 if (customAttribute != nil) { 165 [customAttribute release]; 166 } 167 } 168 169 //cleanup part 2 170 shouldReadCharacters = NO; 171 isCustom = NO; 172} 173 174- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 175{ 176// NSLog(@"%@", string); 177 if (shouldReadCharacters == NO) { 178 return; 179 } 180 181 // this delegate method might be called several times for a single element, 182 // so we have to collect the received data 183 [textCurrentElement appendString:string]; 184 185 //NSLog(@"chars read: %@", string); 186} 187 188- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 189{ 190 //NSLog(@"parsing finished with error"); 191 NSLog([NSString stringWithFormat:@"Error %i, Description: %@, Line: %i, Column: %i", [parseError code], 192 [[parser parserError] localizedDescription], [parser lineNumber], 193 [parser columnNumber]]); 194} 195 196@end 197