我们知道有很多的web services是使用XML格式的,我们可以通过使用XmlListModel来解析我们的XML。但是在有些情况下,我们可能需要使用Javascript来解析XML,这样使得我们可以更加灵活地解析我们所需要的XML数据。比如,通过1个要求,我们可以来解析XML结果中的多个数据。比较而言,XmlListModel只能对XPath路经下(由source属性定义)的数据进行解析。如果需要多个路径,可以通过量次对不同的路径进行查询。固然,我们可能需要1些方法来同步这些查询(如果终究的数据有相互联系的话)。
我们这里就使用我们已有的1个教程“构建首个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⑵9">
<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
/*!
rief 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