在Swift(Xcode v 7.0.1)中解析XML文件并从字典中检索值
我试图用Swift解析XML文件,但在理解NSMutableDictionary如何存储元素中的值时遇到了一点困难在Swift(Xcode v 7.0.1)中解析XML文件并从字典中检索值,xml,swift,google-maps,xml-parsing,Xml,Swift,Google Maps,Xml Parsing,我试图用Swift解析XML文件,但在理解NSMutableDictionary如何存储元素中的值时遇到了一点困难 <packages> <package name="packageone" /> </packages> <test name="testOne"> <classes> <class name="TestClassOne"> <methods>
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
XML文件如下所示
<coord2 count="6">
<markers>
<marker>
<lat>36.99058167</lat>
<lng>-122.06620333</lng>
<timestamp>1444931620</timestamp>
<route>LOOP</route>
<id>7855</id>
<predictions>
,4,5,,6,7,,,,10,,,11,,11,,13,15,,14,,,16,,,0,,,2,,,,,,,,,,,,,,
</predictions>
<update_seconds>10</update_seconds>
<index>4</index>
</marker>
<marker>
<lat>36.99296</lat>
<lng>-122.06517333</lng>
<timestamp>1444934786</timestamp>
<route>UPPER CAMPUS</route>
<id>7860</id>
<predictions>
15,,,14,,,13,12,11,,10,9,,8,,7,,,6,,5,4,,3,2,,1,0,,,,,,,,,,,,,,,
</predictions>
<update_seconds>10</update_seconds>
<index>4</index>
</marker>
</markers>
<curr_time>1444931622</curr_time>
</coord2>
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
现在我只关注“路由”和“时间戳”元素,只是为了了解解析是如何工作的。当我
let t = elements["route"]!
print(t)
print("previous is route")
let u = elements["timestamp"]!
print(u)
print("previous is timestamp")
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
始终是XML文件中具有这些名称的最后一个元素的值。因此,对于我提供的示例XML文件,上面6行代码的输出将是
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
路线是上校区
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
时间戳是1444934786
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
我希望能够区分XML文件中的多个“标记””元素,并检索标记中元素的值。换言之,也可以获取第一个标记中的元素值,而不仅仅是最后一个标记。我该怎么做呢?<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
注意
我已经把你可以复制粘贴到操场上的地图
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
让我们从一个简单的例子开始:
let xml = "<coord2 count=\"3\">"
+ "<markers>"
+ "<marker>"
+ "<item>marker1</item>"
+ "</marker>"
+ "<marker>"
+ "<item>marker2</item>"
+ "<lat>36</lat>"
+ "</marker>"
+ "</markers>"
+ "</coord2>"
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
由于coord2是我们的根标记,我们将创建一个映射到该标记的类-它表示根对象,具有一个标记数组、一个计数属性,也是XMLParser的根委托对象
// Represents a coord2 tag
// It has a count attribute
// and a collection of markers
class Coord2 : ParserBase {
var count = 0
var markers = [Marker]()
override func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
print("processing <\(elementName)> tag from Coord")
if elementName == "coord2" {
// if we are processing a coord2 tag, we are at the root
// of this example
// extract the count value and set it
if let c = Int(attributeDict["count"]!) {
self.count = c
}
}
// if we found a marker tag, delegate further responsibility
// to parsing to a new instance of Marker
if elementName == "marker" {
let marker = Marker()
self.markers.append(marker)
// push responsibility
parser.delegate = marker
// let marker know who we are
// so that once marker is done XML processing
// it can return parsing responsibility back
marker.parent = self
}
}
}
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
其输出如下:
coord has a count attribute of 3
coord has 2 markers
marker item = marker1 and lat = 0
marker item = marker2 and lat = 36
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
我使用下面创建的类从XML数据获取字典
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
您需要添加该类,只需调用下面的函数即可获得字典响应
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
设objXmlParser=BbXmlParser()
让dictResponse=objXmlParser.getdictionaryFromXmlData(数据!)
打印(口述回应)
这是你的字典。:) 在Swift 2.2中:
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
假设您的xml文件位于pc中的任何位置,并将xml文件设置为:
<!DOCTYPE suite SYSTEM "http://.dtd" >
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
现在调用如下函数:
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
let path = NSURL(fileURLWithPath: "xml-file-location" ).URLByAppendingPathComponent("test.xml")
var fileContent = try NSString(contentsOfURL: path, encoding: NSUTF8StringEncoding) as String
let data = fileContent.dataUsingEncoding(NSUTF8StringEncoding) //convert string to data for xml parsing
let xmlParser = NSXMLParser(data: data!) //create xml parser
let xmlRead = XmlParsing() // create the object of that class where function is declared.
xmlParser.delegate = xmlRead //use that object to delegate
xmlParser.parse() // parse the xml
什么时候
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
调用,然后调用解析器函数并执行必要的工作。输出为:
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
test_480
test_481
test_482
test_111
test_112
test_113
更重要的一点是解析器具有重载函数。您可以根据需要使用它们
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
例如,如果您需要阅读任何
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
commented node
从xml文件中,在XmlParsing类中使用以下解析器函数:
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>
func parser(parser: NSXMLParser, foundComment comment: String) {
print(comment)
}
这是查找api详细信息的链接:您是否需要使用NSMutableDictionary/NSMutableArray,或者是否可以创建类来表示Coord2/Marker?我提出这个问题的原因是,如果您可以使用自定义类,那么您可以使用另一种方法来干净地解析XML,并获得更易于管理的代码……感谢您的回复。现在,我愿意接受建议。我对斯威夫特相当陌生,所以我边走边学习。我如何使用自定义类来实现这一点?好的。。。我已经给了你一个答案;请在下面查看。哇,非常感谢@Benzi的帮助。还有一个问题。我应该将XML文件的URL放在哪里?我的机器上没有本地的XML文件。另外,我是否将最后一块代码放在我的
override func viewDidLoad(){..}
函数中?是的,您可以将最后一块代码放在viewDidLoad
中。。。至于URL,到目前为止您是如何使用解析器的?如果您使用类似于parser=NSXMLParser(contentsOfURL:(NSURL(string:)http://xmfile.xml"))!)!像这样编码>然后用它代替最后一个块中的对应行。(我使用的是一个游乐场,所以必须将XML放在一个字符串中。)太棒了。大多数情况下,除了将字符串转换为双精度外,其他一切都正常工作。我在你的回复中看到你将其转换为Int。我需要转换为Double,但它不起作用。我正在尝试var-lat=“”
,var-lati=0.0
,self.lat=foundCharacters
,self.lat=(self.lat作为NSString)。doubleValue
。self.lat
的值为“36.97728”,但是self.lati
的值将保持为0.0如果您使用的是Swift 2.x,Double具有一个接受字符串的初始值设定项。类似于let s=“34.223”;让doubleValue=Double??0//尝试创建一个双精度字符串,否则其0
我认为foundCharacters
对字符串“36.97728”有作用。当我做var lat=“”;self.lat=foundCharacters;让doubleFromlat=Double(self.lat)
,doubleFormat
被赋值nil
。我一直在读,当你试图作为一个双精度的字符串不能被转换时,就会发生这种情况。例如,Double(“abc”)
将是nil
。如果一个问题与另一个问题重复,则将该问题标记为重复而不是回答。无论如何,不要多次发布相同的答案。谢谢谢谢你的建议!这是我的第一个答案,我正在学习:)然后你应该阅读并查看中的各种文章。它将帮助你做出更好的答案(我的意思是,答案遵循网站的指导方针)相关性!=因果关系。你不知道谁投了票:不要以为是和你说话的人。。。
<packages>
<package name="packageone" />
</packages>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_480" />
<include name="test_481" />
<include name="test_482" />
</methods>
</class>
</classes>
</test>
<test name="testOne">
<classes>
<class name="TestClassOne">
<methods>
<include name="test_111" />
<include name="test_112" />
<include name="test_113" />
</methods>
</class>
</classes>
</test>