NSXMLParserDelegate foundCharacters 函数返回空
NSXMLParserDelegate foundCharacters function returning empty
我是 Swift 语言的新手,在解析 XML 时遇到问题。它似乎是可读的,因为 returns 对象计数,但它没有打印值。
这是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)
}
}
问题是该方法的签名不正确。它可能根本不会被调用。应该是:
func parser(parser: NSXMLParser, foundCharacters string: String?) {
tempString += string!
}
请注意,我已从 foundCharacters
中删除 stringByTrimmingCharactersInSet
。你不想在那里这样做,因为它可能需要多次调用 foundCharacters
到 return 一个字符串值,并且 trimming 在这个例程中的净效果是你可以 trim 不仅在字符串的开头和结尾,而且在字符串的中间。 (例如,如果元素值是 "this is a test" 并且在对 foundCharacters
的两次调用中被 return 编辑,一次是 "this is " 一次是 "a test",如果您有 foundCharacter
trim 个字符,它将错误地表示为 "this isa test"。)
而是在 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)
}
}
我是 Swift 语言的新手,在解析 XML 时遇到问题。它似乎是可读的,因为 returns 对象计数,但它没有打印值。
这是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)
}
}
问题是该方法的签名不正确。它可能根本不会被调用。应该是:
func parser(parser: NSXMLParser, foundCharacters string: String?) {
tempString += string!
}
请注意,我已从 foundCharacters
中删除 stringByTrimmingCharactersInSet
。你不想在那里这样做,因为它可能需要多次调用 foundCharacters
到 return 一个字符串值,并且 trimming 在这个例程中的净效果是你可以 trim 不仅在字符串的开头和结尾,而且在字符串的中间。 (例如,如果元素值是 "this is a test" 并且在对 foundCharacters
的两次调用中被 return 编辑,一次是 "this is " 一次是 "a test",如果您有 foundCharacter
trim 个字符,它将错误地表示为 "this isa test"。)
而是在 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)
}
}