2015-07-01 52 views
1

我是Swift語言的新手,我在解析XML時遇到問題。它似乎是可讀的,因爲它返回對象計數,但它不打印值。NSXMLParserDelegate foundCharacters函數返回空

這是XML:

<?xml version="1.0" encoding="utf-8"?> 
<carros> 
    <carro> 
     <nome>Ferrari FF</nome> 
     <desc><![CDATA[A Ferrari FF acaba de ser revelada. Se trata do primeiro modelo da marca a ter tração integral. Além disso, ele conta com um motor dianteiro V12. Se trata de um modelo GT de quatro lugares que não só substitui a 612 mas também atrai um novo tipo de cliente, daquele que gosta de percorrer caminhos mais difíceis que exigem tração integral. Este modelo revolucionário (dentro da marca) tem um novo chassi com entre-eixos maior, além de suspensão independente que incorpora a última geração de amortecedores ajustáveis, além de freios de cerâmica da Brembo. 
    ]]> 
     </desc> 
     <url_info> 
      http://www.ferrari.com/English/GT_Sport%20Cars/CurrentRange/FF/Pages/FF.aspx 
     </url_info> 
     <url_foto> 
      http://www.livroandroid.com.br/livro/carros/esportivos/Ferrari_FF.png 
     </url_foto> 
     <url_video> 
      http://www.livroiphone.com.br/carros/esportivos/ferrari_ff.mp4 
     </url_video> 
     <latitude>44.532218</latitude> 
     <longitude>10.864019</longitude> 
    </carro> 
    <carro> 
     <nome>AUDI GT Spyder</nome> 
     <desc><![CDATA[O mais novo modelo limitado a 333 unidades que vem para preencher a lacuna de modelo top de linha, vaga desde que o cupê do mesmo modelo, há um ano atrás, esgotou todos os pedidos ainda ano passado. 
O segredo do baixo peso é fazer uso de fibra de carbono para boa parte dos painéis de carroceria, e fibra de vidro para os bancos concha. Além disso, o teto da capota é tecido e se retrai em 19 segundos, podendo-se recolhe-lo andando em velocidades de até 50km/h. 
    ]]> 
     </desc> 
     <url_info> 
      http://www.audi.com.br/br/brand/pt.html 
     </url_info> 
     <url_foto> 
      http://www.livroandroid.com.br/livro/carros/esportivos/Audi_Spyder.png 
     </url_foto> 
     <url_video> 
      http://www.livroiphone.com.br/carros/esportivos/audi_gt.mp4 
     </url_video> 
     <latitude>-23.564224</latitude> 
     <longitude>-46.653156</longitude> 
    </carro> 
</carros> 

這是我NSXMLParser代碼,所有的印刷品都還好,除了tempString打印。我不確定,但我認爲foundCharacters函數有問題。

import Foundation 

class XMLCarroParser: NSObject, NSXMLParserDelegate { 

    var carros: Array<Carro> = [] 
    //variaveis auxiliares para o parser 
    var tempString: String = "" 
    var carro: Carro? 

    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) { 

     if(elementName == "carro") { 
      //Tag <carro> encontrada, cria um novo objeto carro 
      carro = Carro() 
      println("creating an object carro") 
     } 

    } 

    func parser(parser: NSXMLParser?!, foundCharacters string: String!) { 
     // Novos caracteres foram encontrados no XML entao cria a string e faz trim 
     tempString += string.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet()) 
    } 

    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 

     if("carros" == elementName) { 
      //Tag de fim </carros> encontrada. Significa que terminou o xml 
      println("destroing the object carro") 
      return 
     } 

     if("carro" == elementName) { 
      //Insere carro no array e limpa o objeto 
      self.carros.append(carro!) 
      carro = nil 
      println("destroing the object carro"); 

      return 
     } 

     /* 
     Se nao é a tag <carro>, pode ser as tags <nome>, <desc>, etc. 
     Copia os valores do XML para o objeto carro 
     Se eistirem tags com o mesmo nome da @property do Carro, o valor sera copiado. 
     */ 
     if(carro != nil) { 
      if("nome" == elementName) { 
       carro!.nome = "nome"; 
       print(" nome ") 
       println(tempString) 
      } else if("desc" == elementName) { 
       carro!.desc = tempString; 
       println(" desc") 
      } else if("url_foto" == elementName) { 
       carro!.url_foto = tempString 
       println(" foto") 
      } else if("url_info" == elementName) { 
       println(" info") 
       carro!.url_info = tempString 
      } else if("url_video" == elementName) { 
       println(" video") 
       carro!.url_video = tempString 
      } else if("latitude" == elementName) { 
       println(" latitude") 
       carro!.latitude = tempString 
      } else if("longitude" == tempString) { 
       println(" longitude") 
       carro!.longitude = tempString 
      } 

      tempString = "" 
     } 
    } 

    func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) { 
     NSLog("failure error: %@", parseError) 
    } 


} 
+0

注意,除了問題,我注意下面,如果你保留你當前的'didEndElement',注意你在那裏有幾個問題(例如,如果'elementName'是'nomo',你保存''nomo'''而不是'tempString';你的測試'「longitude」== tempString'應該是'「longitude」== elementName')。 – Rob

回答

0

問題是該方法的簽名不正確。它可能根本不會被召喚。它應該是:

func parser(parser: NSXMLParser, foundCharacters string: String?) { 
    tempString += string! 
} 

注意,我從foundCharacters刪除stringByTrimmingCharactersInSet。你不想這樣做,因爲可能需要多次調用foundCharacters才能返回單個字符串值,並且在此例程中修剪的淨效果是,不僅可以在開始和結束時刪除空格的字符串,而且還在字符串的中間。 (例如,如果元素值爲「this is a test」,並且在兩次調用中返回foundCharacters,則返回「this is」,再次返回「test」,如果您有修剪字符foundCharacter,則它將錯誤地表示它作爲「這是一個測試」)。

取而代之,在didEndElement中,在那裏保存字符串。


順便說一句,如果Carro是鍵值編碼兼容(如果它是一個NSObject子類容易實現),解析器代碼被簡化:

class XMLCarroParser: NSObject, NSXMLParserDelegate { 

    var carros = [Carro]() 
    var tempString: String? 
    var carro: Carro? 
    let fields = ["nome", "desc", "url_foto", "url_info", "url_video", "longitude", "latitude"] 

    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) { 

     if elementName == "carro" { 
      carro = Carro() 
     } else if contains(fields, elementName) { 
      tempString = "" 
     } 
    } 

    func parser(parser: NSXMLParser, foundCharacters string: String?) { 
     tempString? += string ?? "" 
    } 

    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 
     if elementName == "carro" { 
      self.carros.append(carro!) 
      carro = nil 
     } else if contains(fields, elementName) { 
      carro?.setValue(tempString!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()), forKey: elementName) 
      tempString = nil 
     } 
    } 

    func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) { 
     NSLog("failure error: %@", parseError) 
    } 

} 
+0

它的工作部分...當我使用卡羅?.setValue(tempString!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()),forKey:elementName)它說carro沒有setValue方法..所以我決定使用全部如果只是爲了測試...,它的工作......是否有錯誤使用carro?.setValue? –

+0

@EricLongo'Carro'必須符合關鍵值編碼標準才能正常工作。實現這一目標的最簡單方法是將Carro作爲NSObject的子類。顯然,如果你不想使用'setValue:forKey:',那麼就把你的'didEndElement'保持原樣(儘管顯然是在修改'tempString'並修正我注意到的'nomo'和'longitude'錯誤在我對你原來的問題的評論中)。 – Rob

+0

多數民衆贊成它......我做Carro NSObject的子類...它現在完美..感謝很多。 –