我们知道有很多的web services是使用XML格式的,我们可以通过使用XmlListModel来解析我们的XML。但是在有些情况下,我们可能需要使用Javascript来解析XML,这样使得我们可以更加灵活地解析我们所需要的XML数据。比如,通过一个请求,我们可以来解析XML结果中的多个数据。比较而言,XmlListModel只能对XPath路经下(由source属性定义)的数据进行解析。如果需要多个路径,可以通过多次对不同的路径进行查询。当然,我们可能需要一些方法来同步这些查询(如果最终的数据有互相联系的话)。
我们这里就使用我们已经有的一个教程“构建首个QML应用程序”。在这个应用中,它使用了XmlListModel来解析所得到的XML数据。API的接口为:http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
This XML file does not appear to have any style information associated with it. The document tree is shown below. <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> <gesmes:subject>Reference rates</gesmes:subject> <gesmes:Sender> <gesmes:name>European Central Bank</gesmes:name> </gesmes:Sender> <Cube> <Cube time="2015-04-29"> <Cube currency="USD" rate="1.1002"/> <Cube currency="JPY" rate="131.20"/> <Cube currency="BGN" rate="1.9558"/> <Cube currency="CZK" rate="27.435"/> <Cube currency="DKK" rate="7.4619"/> <Cube currency="GBP" rate="0.71610"/> <Cube currency="HUF" rate="302.55"/> <Cube currency="PLN" rate="4.0120"/> <Cube currency="RON" rate="4.4125"/> <Cube currency="SEK" rate="9.2723"/> <Cube currency="CHF" rate="1.0491"/> <Cube currency="NOK" rate="8.3850"/> <Cube currency="HRK" rate="7.5763"/> <Cube currency="RUB" rate="56.7850"/> <Cube currency="TRY" rate="2.9437"/> <Cube currency="AUD" rate="1.3762"/> <Cube currency="BRL" rate="3.2467"/> <Cube currency="CAD" rate="1.3262"/> <Cube currency="CNY" rate="6.8211"/> <Cube currency="HKD" rate="8.5278"/> <Cube currency="IDR" rate="14212.78"/> <Cube currency="ILS" rate="4.2601"/> <Cube currency="INR" rate="69.7841"/> <Cube currency="KRW" rate="1179.14"/> <Cube currency="MXN" rate="16.8221"/> <Cube currency="MYR" rate="3.9178"/> <Cube currency="NZD" rate="1.4310"/> <Cube currency="PHP" rate="48.743"/> <Cube currency="SGD" rate="1.4557"/> <Cube currency="THB" rate="36.142"/> <Cube currency="ZAR" rate="13.0682"/> </Cube> </Cube> </gesmes:Envelope>
为了能够解析我们的XML数据,我们可以通过如下的方法来解析:
function startParse() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.HEADERS_RECEIVED) { } else if (xhr.readyState == XMLHttpRequest.DONE) { var doc = xhr.responseXML.documentElement; showRequestInfo("xhr length: " + doc.childNodes.length ); for (var i = 0; i < doc.childNodes.length; ++i) { var child = doc.childNodes[i]; for (var j = 0; j < child.childNodes.length; ++j) { if ( child.nodeName === "Cube") { var kid = child.childNodes[j]; var length = kid.childNodes.length; for ( var k = 0; k < length; k ++) { var cube = kid.childNodes[k]; if ( cube.nodeName === "Cube") { var len = cube.attributes.length; var currency = cube.attributes[0].nodeValue; var rate = cube.attributes[1].nodeValue; currencies.append({"currency": currency, "rate": parseFloat(rate)}) } } } } } } } xhr.open("GET", URL); xhr.send(); }
这里我们使用了“XMLHttpRequest”来发送我们的请求,并通过“nodeName”及“nodeValue”来遍历我们的XML数据。最终,我们完成解析我们的XML数据。在项目中,我们定义了“xmlparser.js”文件。
Main.qml
import QtQuick 2.0 import Ubuntu.Components 1.1 import QtQuick.XmlListModel 2.0 import Ubuntu.Components.ListItems 0.1 import Ubuntu.Components.Popups 0.1 import "xmlparser.js" as API /*! \brief MainView with a Label and Button elements. */ MainView { id: root // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "currencyconverterxml.liu-xiao-guo" /* This property enables the application to change orientation when the device is rotated. The default is false. */ //automaticOrientation: true // Removes the old toolbar and enables new features of the new header. useDeprecatedToolbar: false property real margins: units.gu(2) property real buttonWidth: units.gu(9) width: units.gu(50) height: units.gu(75) function convert(from, fromRateIndex, toRateIndex) { var fromRate = currencies.getRate(fromRateIndex); if (from.length <= 0 || fromRate <= 0.0) return ""; return currencies.getRate(toRateIndex) * (parseFloat(from) / fromRate); } function update() { indicator.running = false; } Page { title: i18n.tr("Currency Converter") ListModel { id: currencies ListElement { currency: "EUR" rate: 1.0 } function getCurrency(idx) { return (idx >= 0 && idx < count) ? get(idx).currency: "" } function getRate(idx) { return (idx >= 0 && idx < count) ? get(idx).rate: 0.0 } } ActivityIndicator { id: indicator objectName: "activityIndicator" anchors.right: parent.right running: true } Component { id: currencySelector Popover { Column { anchors { top: parent.top left: parent.left right: parent.right } height: pageLayout.height Header { id: header text: i18n.tr("Select currency") } ListView { clip: true width: parent.width height: parent.height - header.height model: currencies delegate: Standard { objectName: "popoverCurrencySelector" text: model.currency onClicked: { caller.currencyIndex = index caller.input.update() hide() } } } } } } Column { id: pageLayout anchors { fill: parent margins: root.margins } spacing: units.gu(1) Row { spacing: units.gu(1) Button { id: selectorFrom objectName: "selectorFrom" property int currencyIndex: 0 property TextField input: inputFrom text: currencies.getCurrency(currencyIndex) onClicked: PopupUtils.open(currencySelector, selectorFrom) } TextField { id: inputFrom objectName: "inputFrom" errorHighlight: false validator: DoubleValidator {notation: DoubleValidator.StandardNotation} width: pageLayout.width - 2 * root.margins - root.buttonWidth height: units.gu(5) font.pixelSize: FontUtils.sizeToPixels("medium") text: '0.0' onTextChanged: { if (activeFocus) { inputTo.text = convert(inputFrom.text, selectorFrom.currencyIndex, selectorTo.currencyIndex) } } // This is more like a callback function function update() { text = convert(inputTo.text, selectorTo.currencyIndex, selectorFrom.currencyIndex) } } } Row { spacing: units.gu(1) Button { id: selectorTo objectName: "selectorTo" property int currencyIndex: 1 property TextField input: inputTo text: currencies.getCurrency(currencyIndex) onClicked: PopupUtils.open(currencySelector, selectorTo) } TextField { id: inputTo objectName: "inputTo" errorHighlight: false validator: DoubleValidator {notation: DoubleValidator.StandardNotation} width: pageLayout.width - 2 * root.margins - root.buttonWidth height: units.gu(5) font.pixelSize: FontUtils.sizeToPixels("medium") text: '0.0' onTextChanged: { if (activeFocus) { inputFrom.text = convert(inputTo.text, selectorTo.currencyIndex, selectorFrom.currencyIndex) } } function update() { text = convert(inputFrom.text, selectorFrom.currencyIndex, selectorTo.currencyIndex) } } } Button { id: clearBtn objectName: "clearBtn" text: i18n.tr("Clear") width: units.gu(12) onClicked: { inputTo.text = '0.0'; inputFrom.text = '0.0'; } } } Component.onCompleted: { API.startParse(root); } } }
整个项目的源码在:git clone https://gitcafe.com/ubuntu/CurrencyConverterXml.git
时间: 2024-10-16 19:14:48