以 QXmlItem 作为 QXmlQuery 焦点提取子节点值

发布于 2024-12-10 05:57:33 字数 1815 浏览 0 评论 0原文

我一直在尝试从这个 XML 文件中获取节点文本值:

  <!DOCTYPE structure>
  <data>
   <x>
    <id>1</id>
    <nam>tytuł</nam>
    <tab>21</tab>
    <ind>5</ind>
    <pre>TY</pre>
    <khw>C.TY</khw>
   </x>
   <x>
    <id>2</id>
    <nam>autor</nam>
    <tab>21</tab>
    <ind>5</ind>
    <pre>FO</pre>
    <khw>C.FO</khw>
   </x>
   <x>
    <id>3</id>
    <nam>hasło korporatywne</nam>
    <tab>21</tab>
    <ind>5</ind>
    <pre>FN</pre>
    <khw>C.FN</khw>
   </x>
  </data>

我想要做的是获取每个节点及其子节点并将其转换为 QMap。我在获取单个元素方面没有任何问题,但是当通过将 QXmlQuery 的结果设置为焦点来获取子项时,我评估子节点查询的 QString 为空。我使用这段代码:

QXmlResultItems results;
QFile structure("./structure.xml"); // xml file, as described earlier
structure.open(QFile::ReadOnly);

QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");
query.evaluateTo(&results);

QXmlItem next = results.next();
while(!next.isNull()) {
    qDebug() << next.toNodeModelIndex().stringValue(); // everything's fine. It prints contents of <x>'s child nodes
    QXmlQuery childQuery;
    QString r;
    childQuery.setFocus(next);
    childQuery.setQuery("./nam/text()"); // already tested: "/nam/text()", "/nam/string()", "x/nam/string()", "data/x/nam/string()" etc... still no luck.
    childQuery.evaluateTo(&r);
    qDebug() << r; // prints \n but it should print content of <nam> node.

    next = results.next();
}

我使用的软件:直接来自Qt网站的Qt 4.7.2 SDK,Windows和Linux上的QtCreator 2.3.1(在这种特殊情况下没有任何区别,结果是相同的)。我想确定这是我缺乏知识的问题,而不是软件错误,请帮忙

I've been trying to fetch node text values from this XML file:

  <!DOCTYPE structure>
  <data>
   <x>
    <id>1</id>
    <nam>tytuł</nam>
    <tab>21</tab>
    <ind>5</ind>
    <pre>TY</pre>
    <khw>C.TY</khw>
   </x>
   <x>
    <id>2</id>
    <nam>autor</nam>
    <tab>21</tab>
    <ind>5</ind>
    <pre>FO</pre>
    <khw>C.FO</khw>
   </x>
   <x>
    <id>3</id>
    <nam>hasło korporatywne</nam>
    <tab>21</tab>
    <ind>5</ind>
    <pre>FN</pre>
    <khw>C.FN</khw>
   </x>
  </data>

What I want to do is to fetch every node and it's children and convert it to QMap. I have no trouble with fetching single element, but when it comes to fetch children items by setting result of QXmlQuery as a focus, the QString that i evaluate the child node query is empty. I use this piece of code:

QXmlResultItems results;
QFile structure("./structure.xml"); // xml file, as described earlier
structure.open(QFile::ReadOnly);

QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");
query.evaluateTo(&results);

QXmlItem next = results.next();
while(!next.isNull()) {
    qDebug() << next.toNodeModelIndex().stringValue(); // everything's fine. It prints contents of <x>'s child nodes
    QXmlQuery childQuery;
    QString r;
    childQuery.setFocus(next);
    childQuery.setQuery("./nam/text()"); // already tested: "/nam/text()", "/nam/string()", "x/nam/string()", "data/x/nam/string()" etc... still no luck.
    childQuery.evaluateTo(&r);
    qDebug() << r; // prints \n but it should print content of <nam> node.

    next = results.next();
}

Software I use: Qt 4.7.2 SDK directly from Qt website, QtCreator 2.3.1 on Windows and Linux (without any difference in this particular case, results are the same). I want to be sure that's the problem of my lack of knowledge, rather than software bug, please help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

弥繁 2024-12-17 05:57:33

不幸的是,从 Qt 文档中不清楚,当您想要使用 QXmlQuery::setFocus(const QXmlItem& item) 重载来查询子节点时,您应该创建相应的 QXmlQuery< /code> 对象使用 QXmlQuery(const QXmlNamePool& np) 构造函数使它们共享相同的 QXmlNamePool 对象。简而言之,这种共享将查询相互关联起来。

考虑到这一点,您的示例应如下所示:

QFile structure("./structure.xml");
structure.open(QFile::ReadOnly);

QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");

QXmlResultItems results;
query.evaluateTo(&results);

QXmlQuery childQuery(query.namePool());
while (!results.next().isNull()) {
    childQuery.setFocus(results.current());
    childQuery.setQuery("nam/text()");
    QString r;
    childQuery.evaluateTo(&r);
    qDebug() << r;
}

此外,您可以进一步重用初始 QXmlQuery 对象:

QFile structure("./structure.xml");
structure.open(QFile::ReadOnly);

QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");

QXmlResultItems results;
query.evaluateTo(&results);

while (!results.next().isNull()) {
    query.setFocus(results.current());
    query.setQuery("nam/text()");
    QString r;
    query.evaluateTo(&r);
    qDebug() << r;
}

Unfortunately, it is unclear from Qt Documentation that in cases when you want to use QXmlQuery::setFocus(const QXmlItem& item) overload in order to query child nodes, you should create corresponding QXmlQuery objects using QXmlQuery(const QXmlNamePool& np) constructor to make them share the same QXmlNamePool object. Such sharing, simply speaking, relates queries to each other.

Considering this, your example should look like following:

QFile structure("./structure.xml");
structure.open(QFile::ReadOnly);

QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");

QXmlResultItems results;
query.evaluateTo(&results);

QXmlQuery childQuery(query.namePool());
while (!results.next().isNull()) {
    childQuery.setFocus(results.current());
    childQuery.setQuery("nam/text()");
    QString r;
    childQuery.evaluateTo(&r);
    qDebug() << r;
}

Moreover, you can go further and reuse initial QXmlQuery object:

QFile structure("./structure.xml");
structure.open(QFile::ReadOnly);

QXmlQuery query;
query.setFocus(&structure);
query.setQuery("data/x");

QXmlResultItems results;
query.evaluateTo(&results);

while (!results.next().isNull()) {
    query.setFocus(results.current());
    query.setQuery("nam/text()");
    QString r;
    query.evaluateTo(&r);
    qDebug() << r;
}
可爱暴击 2024-12-17 05:57:33

请使用 QStringList 版本,而不是使用 evaluateTo( QString * )。它应该有效。

Instead of using evaluateTo( QString * ) use the QStringList version. It should work.

北凤男飞 2024-12-17 05:57:33

它应该像这样工作:

QDomDocument doc("structure");
QFile file("structure.xml");
if( !file.open( IO_ReadOnly ) )
  return -1;
if( !doc.setContent( &file ) )
{
  file.close();
  return -2;
}
file.close();

QDomElement root = doc.documentElement();
if( root.tagName() != "data" )
  return -3;

QDomNode n = root.firstChild();
while( !n.isNull() )
{
  QDomElement e = n.toElement();
  if( !e.isNull() )
  {
    if( e.tagName() == "x" )
    {
      QMessageBox::information( 0, "X", e.attribute("id", "")+ "\n" + e.attribute("nam", "" ) + "\n" + e.attribute("tab", ""));
    }
  }

  n = n.nextSibling();
}

代码正在为每个 x 执行一个消息框(这台机器上没有 qt,所以现在无法测试它)

It should work like this:

QDomDocument doc("structure");
QFile file("structure.xml");
if( !file.open( IO_ReadOnly ) )
  return -1;
if( !doc.setContent( &file ) )
{
  file.close();
  return -2;
}
file.close();

QDomElement root = doc.documentElement();
if( root.tagName() != "data" )
  return -3;

QDomNode n = root.firstChild();
while( !n.isNull() )
{
  QDomElement e = n.toElement();
  if( !e.isNull() )
  {
    if( e.tagName() == "x" )
    {
      QMessageBox::information( 0, "X", e.attribute("id", "")+ "\n" + e.attribute("nam", "" ) + "\n" + e.attribute("tab", ""));
    }
  }

  n = n.nextSibling();
}

The code is doing a message box for every x (don't have qt on this machine, so can't test it right now)

稚然 2024-12-17 05:57:33

我遇到了同样的问题,解决方案是让 querychildQuery 完全相同。您可以将代码重写为:

while(!next.isNull()) {
    qDebug() << next.toNodeModelIndex().stringValue();
    QString r;
    query.setFocus(next);
    query.setQuery("./nam/text()");
    query.evaluateTo(&r);
    qDebug() << r;

    next = results.next();
}

如果 childQuery 位于另一个过程中,则必须通过引用传递它。

I had the same problem, and the solution was to have the query and childQuery be exactly the same. You could rewrite your code as :

while(!next.isNull()) {
    qDebug() << next.toNodeModelIndex().stringValue();
    QString r;
    query.setFocus(next);
    query.setQuery("./nam/text()");
    query.evaluateTo(&r);
    qDebug() << r;

    next = results.next();
}

if childQuery is to be in another procedure, you have to pass it by reference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文