標籤:
我們知道有很多的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.0import Ubuntu.Components 1.1import QtQuick.XmlListModel 2.0import Ubuntu.Components.ListItems 0.1import Ubuntu.Components.Popups 0.1import "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
如何在QML應用中使用Javascript來解析XML