2015-07-01 56 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的子类...它现在完美..感谢很多。 –