2011-03-23 12 views
8

Básicamente tengo una respuesta XML que se devuelve y una cadena, y necesito bucles a través del xml y almacenar toda la información en una matriz. aquí es el xmliPhone TBXML bucle y de análisis de datos

<?xml version="1.0" encoding="UTF-8"?> 
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schema.2sms.com/2.0/schema/0310_ResponseReportStandard.xsd" Version="1.0"> 
    <Error> 
     <ErrorCode>00</ErrorCode> 
     <ErrorReason>OK</ErrorReason> 
    </Error> 
    <ResponseData> 
     <Identification> 
      <UserID>[email protected]</UserID> 
     </Identification> 
     <Result>2 records were returned</Result> 
     <Detail> 
      <ReportTitle>Message Summary: Today</ReportTitle> 
      <Record> 
       <Destination>447790686158</Destination> 
       <Status>WithNetwork</Status> 
       <GUID><![CDATA[2011-03-22T10:54:22.097Z]]></GUID> 
       <DateSubmitted>2011-03-22T10:54:22.097</DateSubmitted> 
       <DateToSend></DateToSend> 
       <DateSent>2011-03-22T10:54:22.533</DateSent> 
       <DateReceived></DateReceived> 
       <Message><![CDATA[Yet again another test]]></Message> 
       <ID>2011-03-22 10:54:22.250HIHIIOJTFVETW85TS</ID> 
      </Record> 
      <Record> 
       <Destination>447790686158</Destination> 
       <Status>SUCCESS</Status> 
       <GUID><![CDATA[2011-03-22T10:50:40.064Z]]></GUID> 
       <DateSubmitted>2011-03-22T10:50:40.063</DateSubmitted> 
       <DateToSend></DateToSend> 
       <DateSent>2011-03-22T10:50:42.473</DateSent> 
       <DateReceived>2011-03-22T10:50:54.570</DateReceived> 
       <Message><![CDATA[This is a test]]></Message> 
       <ID>2011-03-22 10:50:40.210DRUDVMCEZGETW85TS</ID> 
      </Record> 
      <ReportPage ReportID="775797" ItemsPerPage="25" Page="1" TotalItems="2" /> 
     </Detail> 
    </ResponseData> 
</Response> 

necesito los 2 <records> y todo lo que hay datos que se almacenarán en una matriz. así que ....

una matriz registros -> tabla de registros -> conjunto de registros, cada uno de los datos ....

he estado sentado aquí tratando de resolver esto utilizando TBXML que es bastante fácil agarrar un solo nodo .... pero no puedo hacer esto :(NSXMLParser

+2

Por favor, ver si se puede aceptar más respuestas. Parece que tiene respuestas razonables a algunas de sus preguntas que no se aceptan. – occulus

Respuesta

14

bien, el primer paso sería hacer una clase que va a analizar los datos. Llámelo RecordParser, por ejemplo. Ahora necesitamos agregar un par de métodos en el encabezado, así como un NSMutableArray.

@interface RecordParser : NSObject { 
    NSMutableArray *records;  
} 
@property(nonatomic,retain)NSMutableArray *records; 

-(void)loadRecords:(NSString *)records; 
-(void)traverseElement:(TBXMLElement *)element; 

@end 

Ahora, continúe y cargue en su implementación. Ahora necesitamos implementar esos dos métodos para hacer lo que queremos que hagan.

- (void)loadRecords:(NSString *)records { 
    NSString *someXML = @"http://www.something.com/somexml.xml"; 
    TBXML *tbxml = [[TBXML tbxmlWithURL:[NSURL URLWithString:someXML]] retain]; 

    records = [NSMutableArray array]; 
    [records retain]; 

    if (tbxml.rootXMLElement) 
     [self traverseElement:tbxml.rootXMLElement]; 
    [tbxml release]; 
} 

Básicamente ese método tomará el archivo XML en cuestión y comenzará el proceso de análisis. Además, estás inicializando tu matriz y reteniéndola. Ahora llegamos al queso.

- (void) traverseElement:(TBXMLElement *)element { 
    do { 
     if (element->firstChild) 
      [self traverseElement:element->firstChild]; 

     if ([[TBXML elementName:element] isEqualToString:@"Record"]) { 
      TBXMLElement *destination = [TBXML childElementNamed:@"Destination" parentElement:element]; 
      TBXMLElement *status = [TBXML childElementNamed:@"Status" parentElement:element]; 
      TBXMLElement *guid = [TBXML childElementNamed:@"GUID" parentElement:element]; 
      TBXMLElement *dateSub = [TBXML childElementNamed:@"DateSubmitted" parentElement:element]; 
      TBXMLElement *dateToSend = [TBXML childElementNamed:@"DateToSend" parentElement:element]; 
      TBXMLElement *dateSent = [TBXML childElementNamed:@"DateSent" parentElement:element]; 
      TBXMLElement *dateReceived = [TBXML childElementNamed:@"DateReceived" parentElement:element]; 
      TBXMLElement *message = [TBXML childElementNamed:@"Message" parentElement:element]; 
      TBXMLElement *id = [TBXML childElementNamed:@"ID" parentElement:element]; 

      [records addObject:[NSArray arrayWithObjects: 
            [TBXML textForElement:destination], 
            [TBXML textForElement:status], 
            [TBXML textForElement:guid], 
            [TBXML textForElement:dateSub], 
            [TBXML textForElement:dateToSend], 
            [TBXML textForElement:dateSent], 
            [TBXML textForElement:dateReceived], 
            [TBXML textForElement:message], 
            [TBXML textForElement:id],nil]]; 
     } 
    } while ((element = element->nextSibling)); 
} 

Básicamente lo que hace es el método transversal del archivo XML en busca de un elemento con el nombre que está buscando, entonces se agarra los datos de los nodos secundarios. Además, los datos se agregan a la matriz records. Básicamente, cuando termine, debe tener los datos que desea en su matriz records, que puede manipular todo lo que desee.

Esto es, no está comprobado. No me culpes si hace explotar tu computadora y mata a tu gato. Normalmente no tomaría todo el trabajo para escribir un método completo como este, pero me gusta TBXML. Por favor, déjeme saber si funciona. I realmente agradecería saber.

+0

¡SÍ! gracias, funciona exactamente como yo también quiero! Pero estoy en otro problema con la selección de entrys paticulares de la matriz que se utilizará en una celda de tableview ... Pero muchas gracias se curó mi dolor de cabeza de 2 días! – MrPink

+0

@MrPink: solo tiene que poner el 'objectAtIndex' de la matriz que desea mostrar en su tabla en' cellForRowAtIndexPath'. –

+0

cell.textLabel.text = [NSString stringWithFormat: @ "% @", [records objectAtIndex: indexPath.row]]; esto es lo que estoy usando, pero está imprimiendo todo lo que está dentro de cada registro de la matriz – MrPink

0

uso de Apple, sino que hizo ser la vieja escuela y todo pero es muy eficiente

Configuración de su XMLParser en consecuencia (utilizar el NSXMLParserDelegate. protocolo).

Una vez que su El analizador llama a la llamada de delegado parser:didStartElement:namespaceURI:qualifiedName:attributes: y el elementName es igual a Record (de lo que parezca querer).

Alloc 'init' un NSMutableDictionary. Luego, como en el caso anterior, si elementName es igual a Destination, entonces [myDictionary setObject: elementName forKey: @"Destination"] y et cætera.

Espero que haya ayudado :).

pequeña nota al margen: prefiera utilizando Apple's "tecnología" en lugar de 3 partes: es más eficiente y las posibilidades son infinitas .

+2

Sin embargo, se ha demostrado que TBXML es mucho más rápido en el análisis que 'NSXMLParser'. Yo uso TBXML y me encanta. :) –

+0

Es cierto y así es como me gustaría hacerlo. sudo ¿cómo usarías tbxml para analizar a través de mi xml anterior? – MrPink

-2

Es mejor utilizar NSXMLParser, porque es una publicación oficial de Apple.

Toda la documentación de NSXMLParser es here.

Además, aquí hay un NSXMLParser Tutorial.

+7

NSXMLParser es 3 veces más lento que TBXML. El hecho de que "Apple" hizo eso no lo hace mejor. – Sagiftw

1

Escribí la función recursiva para analizar cualquier xml creado correctamente con la biblioteca TBXML.

En mi proyecto tengo una clase para analizar XML. Tiene un método de clase llamado: + (id) infoOfElement: (TBXMLElement *) elemento

Modo de empleo:

TBXML *tbxml = [TBXML tbxmlWithXMLData:yourData]; 
TBXMLElement *rootXMLElement = tbxml.rootXMLElement; 

id parsedData = [self infoOfElement: rootXMLElement]; 

    //return NSString or NSDictionary ot NSArray of parsed data 
    + (id) infoOfElement: (TBXMLElement*) element 
    { 
     if (element->text) 
      return [TBXML textForElement:element]; 
     NSMutableDictionary *info = [NSMutableDictionary new]; 
     TBXMLAttribute *attribute = element->firstAttribute; 
     if (attribute) { 
      do { 
       [info setValue:[TBXML attributeValue:attribute] forKey:[TBXML attributeName:attribute]]; 
       attribute = attribute -> next; 
      } while (attribute); 
     } 
     TBXMLElement *child = element->firstChild; 
     if (child){ 
      TBXMLElement *siblingOfChild = child->nextSibling; 
      //If we have array of children with equal name -> create array of this elements 
      if ([[TBXML elementName:siblingOfChild] isEqualToString:[TBXML elementName:child]]){ 
       NSMutableArray *children = [NSMutableArray new]; 
       do { 
        [children addObject:[self infoOfElement:child]]; 
        child = child -> nextSibling; 
       } while (child); 
       return [NSDictionary dictionaryWithObject:children forKey:[TBXML elementName:element]]; 
      } 
      else{ 
       do { 
        [info setValue:[self infoOfElement:child] forKey:[TBXML elementName:child]]; 
        child = child -> nextSibling; 
       } while (child); 
      } 
     }    
     return info; 
    }