2011-05-15 14 views
9

Estoy buscando un breve ejemplo/tutorial sobre cómo leer, modificar un valor y escribir un archivo xml usando cocoa. Todo lo que encontré es simple (solo lectura o escritura) o complex (es un editor completo de xml).Leer, modificar, escribir archivo xml en cocoa

Este parece ser un escenario de uso bastante estándar, así que estoy esperando que hay algo por ahí ...

+0

posible duplicado de [Cocoa/Obj-C lector de archivos XML simple - necesita ayuda] (http://stackoverflow.com/questions/5274513/cocoa-obj-c-simple-xml-file-reader-need-help) –

+1

Entre otros: [Extraer información de XML] (http://stackoverflow.com/questions/3739854/) | [Analizando XML] (http://stackoverflow.com/questions/1089737/parsing-xml-in-cocoa) | [Práctica recomendada para analizar XML] (http://stackoverflow.com/questions/2237757/) | [Leer/Escribir XML] (http://stackoverflow.com/questions/1072979/) –

+1

Gracias, pero estoy buscando un ejemplo que muestre cómo leer, modificar __y__ escribir un árbol xml. Los 'duplicados' no hacen eso. Supongamos que tengo (entre otras cosas) un contador simple en un archivo xml: . ¿Cómo lo analizo, lo incremento y lo vuelvo a escribir en el archivo? – hanno

Respuesta

6

Tenía un error cuando afirmé que no se podían escribir tales elementos. Apple tiene dos analizadores XML, uno para NSDictionary/NSArray/NSString/NSNumber/etc. objetos y uno llamado NSXMLDocument.

He eliminado el código anterior, que era compatible con Mac OS X 10.3; el código que se menciona a continuación le permitirá tener archivos xml que contengan las etiquetas y los atributos que desee. En mi ejemplo, el código va a crear un archivo XML que tiene el siguiente aspecto:

< raíz > <contador/contador> </root >

Nota: Usted puede incluso quitar el 'contador 'y cambie el nombre' raíz 'por' contador ', si desea reducirlo aún más.

El nuevo código es compatible con Mac OS X 10.4 y posterior; está probado y funciona fuera de la caja:

- (void)incrementCounter 
{ 
    NSXMLDocument *xmlDoc; 
    NSError   *error; 
    NSURL   *url; 
    NSXMLElement *root; 
    id    item; 
    NSData   *data; 
    NSArray   *children; 
    int    counter; 
    NSString  *pathname; 

    pathname = [@"~/myFile" stringByExpandingTildeInPath]; 
    url = [NSURL fileURLWithPath:pathname]; 

    xmlDoc = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyXML error:&error]; 
    if(xmlDoc) 
    { 
     root = [xmlDoc rootElement]; 
    } 
    else 
    { 
     root = [NSXMLNode elementWithName:@"root"]; 
     xmlDoc = [[NSXMLDocument alloc] initWithRootElement:root]; 
    } 

    // fetch value: 
    children = [root nodesForXPath:@"counter" error:&error]; 
    item = [children count] ? [children objectAtIndex:0] : NULL; 

    // modify value: 
    counter = item ? [[item stringValue] intValue] : 0; 
    counter++; 
    if(NULL == item) 
    { 
     item = [NSXMLNode elementWithName:@"counter" stringValue:@"0"]; 
     [root insertChild:item atIndex:0]; 
    } 
    [item setStringValue:[[NSNumber numberWithInt:counter] stringValue]]; 

    // write: 
    data = [xmlDoc XMLData]; 
    [data writeToURL:url atomically:YES]; 
} 
+0

Esta respuesta no tiene ningún sentido para mí. – hanno

+0

He vuelto a escribir mi respuesta. Si necesita soportar Mac OS X por debajo de 10.4, tendré que volver a escribir mi respuesta. Todo depende de si tiene la clase NSXMLDocument disponible. –

+0

¿Lo consiguió trabajando con el nuevo código anterior o sigue teniendo problemas? ... Intenta invocar [autoincrementoCuadro]; de -awakeFromNib en un proyecto completamente nuevo; debe generar 'myFile' en su directorio de inicio e incrementar el contador cada vez que ejecute el programa. –

-4

Si no está familiarizado con xpath s, entonces le sugiero que lea sobre ellos, xpath s son una forma de encontrar nodos en el árbol xml.

+5

Eso no es respuesta, hijo ... Es hacer una pregunta específica ... y aconsejarle que "lea" en xpaths es grosero. Estoy de acuerdo con el OP ... Personalmente, puedo encontrar MILLONES de maneras de leer XML en cacao, pero por mi vida _no puedo encontrar una forma simple, fácil de ver, de convertir un NSArray o NSDictionary, etc. un XML "Objeto" - ¡por mi vida! –

2

Aquí está mi solución al problema - sólo la parte donde escribo el archivo que fue leída y analizada con anterioridad ...

Uso la solución de PacMan-- Encontré el problema de que el archivo de salida xml no estaba formateado muy bien (sin saltos de línea en absoluto).

El otro punto es, usualmente prefiero usar XPath navegando a través de un documento XML.

Mi código es parte de una clase, así que tengo una propiedad para cada nodo (NSString * cfaLayout y NSInteger BitsPerPixel):

-(BOOL) savePropertiesFile{ 
BOOL isSuccess=FALSE; 
NSError* error; 
NSXMLElement* currentElement; 
NSArray* nodes; 

/* parse existing url file before saving it to new url */ 
if([_documentUrl checkResourceIsReachableAndReturnError:&error]==YES){ 
    self.document=[[NSXMLDocument alloc] 
           initWithContentsOfURL:_documentUrl 
           options:0 
           error:&error]; 

    /* check top node */ 
    nodes=[_document nodesForXPath:@"/ImageFormat-Properties" 
                error:&error]; 
    if([nodes count]==0){ 
     return FALSE; 
    } 

    /* cfa layout */ 
    nodes=[_document nodesForXPath:@"/ImageFormat-Properties/ImageFormatDetails/CFALayout[text()]" 
                error:&error]; 
    if([nodes count]>0){ 
     currentElement=[nodes objectAtIndex:0]; 
     [currentElement setStringValue:[_cfaLayout lowercaseString]]; 
    } 
    else{ 
     return FALSE; 
    } 

    /* bitsPerPixel */ 
    nodes=[_document nodesForXPath:@"/ImageFormat-Properties/ImageFormatDetails/BitsPerPixel[text()]" 
                error:&error]; 
    if([nodes count]>0){ 
     currentElement=[nodes objectAtIndex:0]; 
     [currentElement setStringValue:[NSString stringWithFormat: @"%ld", (long)_bitsPerPixel]]; 
    } 
    else{ 
     return FALSE; 
    } 
} 
[_document setDocumentContentKind:NSXMLDocumentXMLKind]; 
[_document setCharacterEncoding:@"UTF-8"]; 
[_document validateAndReturnError:&error]; 
if(error){ 
    return FALSE; 
} 

[self setDocumentUrl:_documentSaveAsUrl]; 
NSData* xmlData=[_document XMLDataWithOptions:NSXMLNodePrettyPrint]; 
isSuccess=[xmlData writeToURL:_documentSaveAsUrl atomically:YES]; 

return isSuccess; 

}

Tal vez útil para alguien ...