QML XmlListModel中的多个嵌套级别

QML XmlListModel中的多个嵌套级别,qml,nested,Qml,Nested,给定以下具有2个嵌套级别的XML源: <papers> <paper id="1"> <authors> <author name="John Doe" /> <author name="Jane Doe" /> </authors> </paper> <paper id="2"> <authors> <auth

给定以下具有2个嵌套级别的XML源:

<papers>
  <paper id="1">
    <authors>
      <author name="John Doe" />
      <author name="Jane Doe" />
    </authors>
  </paper>
  <paper id="2">
    <authors>
      <author name="John Appleseed" />
    </authors>
  </paper>
</papers>
它将包含所有3位作者,而不仅仅是第一篇论文中的2位“Doe”作者。我可以在角色中添加索引(
authors/author[1]
),但我现在不知道将有多少论文和作者。定义author1,author2,…,author99感觉不是正确的方法

如何告诉
XmlListModel
我只想要
ListView
中一篇文章的作者

ListView {
  model: myPapers 
  delegate: Text { text: author }
}
现在显示:

John Doe
Jane Doe
John Appleseed <-- don't want this one
johndoe
无名氏

John Appleseed通过修改
ListView
XmlListModel
的查询来玩弄@danielfranca的解决方案:

ListView {
  model: XmlListModel {
    query: "/paper/authors["+(index+1)+"]"
  }
  Text { text: author }
}

这是可行的,但是。。。在我的用例中,XML源是一个URL,这意味着这将为每个列表创建另一个HTTP请求。这是不必要的,因为第一次请求时数据已经存在。有人想要更好的解决方案吗?

通过修改
列表视图中
XmlListModel
的查询来使用@danielfranca的解决方案:

ListView {
  model: XmlListModel {
    query: "/paper/authors["+(index+1)+"]"
  }
  Text { text: author }
}

这是可行的,但是。。。在我的用例中,XML源是一个URL,这意味着这将为每个列表创建另一个HTTP请求。这是不必要的,因为第一次请求时数据已经存在。有没有更好的解决方案?

做了更多的挖掘,并对更多的人进行了窃听,最终的答案是:没有,这是不可能的使用标准的
XmlListModel
。你必须推出自己的解决方案

以下是我的解决方案的一个片段,以供将来参考-实现借鉴Tim Besard的代码:

项目{
属性布尔加载:false
属性布尔错误:false
属性ListModel文件:ListModel{}
属性字符串源:“http://example.com/papers.xml"
函数fetch(){
var doc=新的XMLHttpRequest();
doc.onreadystatechange=函数(){
错误=错误;
if(doc.readyState==XMLHttpRequest.DONE){
如果(单据状态!=200){
错误=真;
}否则{
var rootNode=doc.responseXML.documentElement;
parsePapers(rootNode);
}
加载=假;
}
}
加载=真;
打开文档(“获取”,源代码);
doc.send();
}
函数解析(rootNode){
文件。清除();
对于(变量i=0;i
这个解决方案不仅比
XmlListModel
解决方案复杂得多:而且似乎QML只有基本的XML解析器功能


最后,如果“对同一资源的多个HTTP请求”对您不重要,您可以使用。

进行了更多的挖掘,并对更多的人进行了窃听,最终的答案是:不,对于标准的
XmlListModel
,这是不可能的。你必须推出自己的解决方案

以下是我的解决方案的一个片段,以供将来参考-实现借鉴Tim Besard的代码:

项目{
属性布尔加载:false
属性布尔错误:false
属性ListModel文件:ListModel{}
属性字符串源:“http://example.com/papers.xml"
函数fetch(){
var doc=新的XMLHttpRequest();
doc.onreadystatechange=函数(){
错误=错误;
if(doc.readyState==XMLHttpRequest.DONE){
如果(单据状态!=200){
错误=真;
}否则{
var rootNode=doc.responseXML.documentElement;
parsePapers(rootNode);
}
加载=假;
}
}
加载=真;
打开文档(“获取”,源代码);
doc.send();
}
函数解析(rootNode){
文件。清除();
对于(变量i=0;i
这个解决方案不仅比
XmlListModel
解决方案复杂得多:而且似乎QML只有基本的XML解析器功能


最后,如果“对同一资源的多个HTTP请求”对您不重要,您可以使用。

从未尝试过,但如果您向查询添加索引,它可能会起作用?类似于这里所做的:谢谢@danielfranca,请参阅下面我的较长回复,它有效。。。但是…从未尝试过,但如果您向查询添加索引,它可能会起作用?类似于这里所做的:谢谢@danielfranca,请参阅下面我的较长回复,它有效。。。但是
Item {
    property bool loading: false
    property bool error: false
    property ListModel papers: ListModel{}
    property string source: "http://example.com/papers.xml"

    function fetch() {
        var doc = new XMLHttpRequest();
        doc.onreadystatechange = function() {
            error = false;
            if (doc.readyState === XMLHttpRequest.DONE) {
                if (doc.status != 200) {
                    error = true;
                } else {
                    var rootNode = doc.responseXML.documentElement;
                    parsePapers(rootNode);
                }
                loading = false;
            }
        }
        loading = true;
        doc.open("GET", source);
        doc.send();
    }

    function parsePapers(rootNode) {
        papers.clear();
        for (var i=0; i < rootNode.childNodes.length; ++i) {
            var node = rootNode.childNodes[i];
            if (node.nodeName == "paper") {
                [snip]...[/snip]
            }
        }
    }
}