如何在QML应用中使用Javascript来解析XML

185 篇文章 7 订阅
159 篇文章 2 订阅

我们知道有很多的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);
        }
    }
}


  


整个项目的源码在: https://github.com/liu-xiao-guo/CurrencyConverterXml



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值