在Swift(Xcode v 7.0.1)中解析XML文件并从字典中检索值

在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>

我试图用Swift解析XML文件,但在理解NSMutableDictionary如何存储元素中的值时遇到了一点困难

<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>