crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

3 страниц V   1 2 3 >  
Ответить в данную темуНачать новую тему
> Xml - обращение к дочернему элементу
FladeX
  опции профиля:
сообщение 27.3.2009, 12:18
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 67
Регистрация: 20.2.2009
Пользователь №: 564

Спасибо сказали: 0 раз(а)




Репутация:   0  


Структура xml:
<help>
    <page id="page01">
        <title>title of page01</title>
        <message>text</message>
    </page>
    ...
    <page id="page99">
        <title>title of page99</title>
        <message>text</message>
    </page>
</help>

Нужно по id найти в нем <page>, а затем получить оттуда содержимое <message>. Пытался делать например так:
    QDomElement docElem;
    docElem = doc.elementById("page01");
        QDomNodeList lstNodes(docElem.childNodes()));
        for (int n=0; n<lstNodes.count(), n++)
        {
            childElem = lstNodes.at(n)::toElement();
            if (childElem.tagName == "message")
            {
                message = childElem.text();
            }
        }

Но не получается... Как же правильно тогда?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 27.3.2009, 14:22
Сообщение #2


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Начну с того, что в приведенном Вами коде очень много ошибок, что очень неприятно при отладке. Надо быть поокуратнее.
Цитата
QDomElement QDomDocument::elementById ( const QString & elementId )

Returns the element whose ID is equal to elementId. If no element with the ID was found, this function returns a null element.

Since the QDomClasses do not know which attributes are element IDs, this function returns always a null element. This may change in a future version.

Т.е. насколько я понимаю, этот метод всегда вернет нулевой елемент.
Я сделал так:
    QDomElement docElem;
    QDomNodeList lstNodes(domDocument.elementsByTagName("page"));
        for (int n=0; n<lstNodes.count(); n++)
        {
            QDomElement childElem = lstNodes.at(n).toElement();
            if (childElem.attribute("id") == "page01")
            {
                QDomElement child = childElem.lastChild().toElement();
                qDebug() << child.text();
            }
        }

Данный код у меня работает. Может не самое оптимальное решение, кто знает как сделать лучше раскажите :rolleyes:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
FladeX
  опции профиля:
сообщение 27.3.2009, 14:57
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 67
Регистрация: 20.2.2009
Пользователь №: 564

Спасибо сказали: 0 раз(а)




Репутация:   0  


Выдает ошибку
crosses initialization of ‘QDomNodeList lstNodes’

на строке
            QDomElement childElem = lstNodes.at(n).toElement();

что не так?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 27.3.2009, 15:16
Сообщение #4


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


???
Я так понимаю, что childElem у Вас где-то уже объявлен.
Сделайте просто
childElem = lstNodes.at(n).toElement();

И domDocument, в Вашем случае объявлен как doc
Отпишитесь о результате. Если что выложу компилябильный проект.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
FladeX
  опции профиля:
сообщение 27.3.2009, 15:23
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 67
Регистрация: 20.2.2009
Пользователь №: 564

Спасибо сказали: 0 раз(а)




Репутация:   0  


childElem ранее объявлен не был.
Замена строки не помогла, ошибка та же самая...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 27.3.2009, 15:47
Сообщение #6


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


копируем куда-нибудь проект QTDIR/examples/xml/dombookmarks
В файле xbeltree.cpp ищем функцию bool XbelTree::read(QIODevice *device)
Что бы не мучаться, заменяем весь ее код, на следущий:
Раскрывающийся текст
bool XbelTree::read(QIODevice *device)
{
    QString errorStr;
    int errorLine;
    int errorColumn;

    if (!domDocument.setContent(device, true, &errorStr, &errorLine,
                                &errorColumn)) {
        QMessageBox::information(window(), tr("DOM Bookmarks"),
                                 tr("Parse error at line %1, column %2:\n%3")
                                 .arg(errorLine)
                                 .arg(errorColumn)
                                 .arg(errorStr));
        return false;
    }

    QDomElement docElem;
    QDomNodeList lstNodes(domDocument.elementsByTagName("page"));
        for (int n=0; n<lstNodes.count(); n++)
        {
            QDomElement childElem = lstNodes.at(n).toElement();
            if (childElem.attribute("id") == "page01")
            {
                QDomElement child = childElem.lastChild().toElement();
                qDebug() << child.text();
            }
        }

    return true;
}



Рядом с exe-шником кладем ваш файл
Раскрывающийся текст
<?xml version="1.0" encoding="UTF-8"?>
<help>
    <page id = "page01">
        <title>title of page01</title>
        <message>text1</message>
    </page>
    <page id = "page99">
        <title>title of page99</title>
        <message>text2</message>
    </page>
</help>


Компилируем, смотрим что выводит qDebug();
Не забываем отписаться о результатах.

P.S. У меня все выше описанное прекрасно работает.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Kagami
  опции профиля:
сообщение 27.3.2009, 18:15
Сообщение #7


Старейший участник
****

Группа: Участник
Сообщений: 601
Регистрация: 2.2.2009
Пользователь №: 523

Спасибо сказали: 101 раз(а)




Репутация:   9  


Есть решение немного по-изящнее:
Раскрывающийся текст
    QDomElement root = domDocument.documentElement();
    QDomElement child = root.firstChildElement("page");
    while (!child.isNull()) {
        if (child.attribute("id") == "page01") {
            QDomElement message = child.firstChildElement("message");
            qDebug() << child.text();
        }
        child = child.nextSiblingElement("page");
    }

Перебираем только нужные элементы и не чувствительны к положению <message> - в предыдущем примере он обязан находиться в конце.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 27.3.2009, 23:27
Сообщение #8


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Цитата(Kagami @ 27.3.2009, 18:15) *
Есть решение немного по-изящнее:

Не буду врать, по специфике своей работы никак с xml сталкиваться не приходилось. Просто было интересно разобраться, вот и помог. Ваш же пример выдаёт не то что мы ожидаем. В топикстарте написано, что требуется вернуть данные тега "message", у Вас же получается следущее
Цитата
"title of page01text1"

а надо
Цитата
"text1"



Цитата(Kagami @ 27.3.2009, 18:15) *
в предыдущем примере он обязан находиться в конце.

Да, я исходил из структуры файла :rolleyes:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Kagami
  опции профиля:
сообщение 27.3.2009, 23:33
Сообщение #9


Старейший участник
****

Группа: Участник
Сообщений: 601
Регистрация: 2.2.2009
Пользователь №: 523

Спасибо сказали: 101 раз(а)




Репутация:   9  


Цитата(igor_bogomolov @ 27.3.2009, 23:27) *
Ваш же пример выдаёт не то что мы ожидаем.

Упс, небольшая очепятка всралась :)
Правильно так:
qDebug() << message.text();
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 28.3.2009, 3:34
Сообщение #10


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Kagami @ 28.3.2009, 2:33) *
.text()
по моему опыту, лучше избегать применения этой функции, т.к. она рекурсивная, т.е. схватит все вложенные тэги, часто это неподходящий вариант. Лучше использовать data() или value().

П.С. еслиб не простуда, привел бы пример, но нагретая голова плохо соображает.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V   1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 11:38