Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 6

Qt-interest Archive, June 2007
QDomDocument::elementById() Implementation


Message 1 in thread

Hi folks,

I've given a quick go at trying to implement QDomDocument::elementById() via 
my own subclass FDomDocument. I've just included the code here with a simple 
test script testfdomdocument.cpp as an attachment with this email.

Any ideas/opinions on the implementation? I'm about to use it in my project so 
if it's a load of crap, I'd like to hear so now :) I can't understand why 
Trolltech didn't implement this functionality. Even if my version is a load 
of rubbish you would think that it wouldn't be terribly hard to do???

Happy hackin,
Dec
/***************************************************************************
/***************************************************************************
 *   Copyright (C) 2007 by Declan McGrath               *
 *   declanmcgrath@xxxxxxxxxxxx   					   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *									   *
 *  This program is open source.  For license terms, see the LICENSE 	   *
 *  and COPYING files							   *. 
 ***************************************************************************/
#include "fdomdocument.h"

FDomDocument::FDomDocument()
{
}

FDomDocument::~FDomDocument()
{
}

QDomElement FDomDocument::elementById (const QString& elementId)
{
    return this->elementByIdAsLowerCase(elementId); // default behaviour
}

QDomElement FDomDocument::elementByIdAsLowerCase (const QString& elementId)
{
    const QDomElement& docElement = this->documentElement();
    return this->nestedElementById(docElement, elementId, "id");
}

QDomElement FDomDocument::elementByIdAsUpperCase (const QString& elementId)
{
    const QDomElement& docElement = this->documentElement();
    return this->nestedElementById(docElement, elementId, "ID");
}

QDomElement FDomDocument::elementByIdAsCapitalCase (const QString& elementId)
{
    const QDomElement& docElement = this->documentElement();
    return this->nestedElementById(docElement, elementId, "Id");
}

QDomElement FDomDocument::elementByIdAsCustomAttribute (const QString& attributeName, const QString& attributeValue)
{
    const QDomElement& docElement = this->documentElement();
    return this->nestedElementById(docElement, attributeValue, attributeName);
}

QDomElement FDomDocument::nestedElementById (const QDomElement& anElement,
    const QString& targetAttributeValue, const QString& targetAttributeName) const
{
    QString curAttributeValue = anElement.attribute(targetAttributeName);
    if (targetAttributeValue == curAttributeValue)
    {
        return anElement;
    }
    else // matching attribute not found
    {// check child elements for matching attribute
        return searchChildElements(anElement, targetAttributeValue, targetAttributeName);
    }
}

QDomElement FDomDocument::searchChildElements(const QDomElement& anElement,
    const QString& targetAttributeValue, const QString& targetAttributeName) const
{
    for(QDomNode n = anElement.firstChild(); !n.isNull(); n = n.nextSibling())
    {
        const QDomElement childElement = n.toElement();
        if (!childElement.isNull()) // true if node is of type element
        {
            QDomElement curElement = this->nestedElementById(childElement, targetAttributeValue, targetAttributeName);

            if (curElement.attribute(targetAttributeName) == targetAttributeValue)
            {
                return curElement;
            }
            // otherwise continue looping thru siblings till out of puff...
        }
    }

    // If we get there it means that there were no matches,
    // thus, return an empty node
    QDomElement nullDomElement;
    nullDomElement.clear();
    return nullDomElement;
}
/***************************************************************************
 *   Copyright (C) 2007 by Declan McGrath               *
 *   declanmcgrath@xxxxxxxxxxxx   					   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *									   *
 *  This program is open source.  For license terms, see the LICENSE 	   *
 *  and COPYING files							   *. 
 ***************************************************************************/
#ifndef FDOMDOCUMENT_H
#define FDOMDOCUMENT_H

#include <QtXml>
#include <QtDebug>

/**
	@author Declan McGrath <declanmcgrath@xxxxxxxxxxxx>
*/
class FDomDocument : public QDomDocument
{
public:
    FDomDocument();
    ~FDomDocument();

    QDomElement elementById (const QString& elementId);
    QDomElement elementByIdAsLowerCase (const QString& elementId);
    QDomElement elementByIdAsUpperCase (const QString& elementId);
    QDomElement elementByIdAsCapitalCase (const QString& elementId);
    QDomElement elementByIdAsCustomAttribute (const QString& attributeName, const QString& attributeValue);


private:
    QDomElement nestedElementById (const QDomElement& anElement,
        const QString& targetAttributeName, const QString& targetAttributeValue) const;
    QDomElement searchChildElements(const QDomElement& anElement,
        const QString& targetAttributeName, const QString& targetAttributeValue) const;
};

#endif
/***************************************************************************
/***************************************************************************
 *   Copyright (C) 2007 by Declan McGrath               *
 *   declanmcgrath@xxxxxxxxxxxx   					   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *									   *
 *  This program is open source.  For license terms, see the LICENSE 	   *
 *  and COPYING files							   *. 
 ***************************************************************************/

#include <QtTest/QtTest>
#include <QtXml>
#include <QtDebug>
#include "../../../src/fdomdocument.cpp"

class TestFDomDocument: public QObject
{
    Q_OBJECT

private:
    QString m_sampleXml;
    FDomDocument m_domDoc;

private slots:
    void initTestCase()
    {
        m_sampleXml +=    "<div id='myDivList'>";
        m_sampleXml +=        "<div style='color:red; 'id='myDiv1'>Red text</div>";
        m_sampleXml +=        "<div style='color:blue;' id='myDiv2'>Blue text</div>";
        m_sampleXml +=        "<div style='color:black;' id='myDiv3'>Black text</div>";
        m_sampleXml +=        "<div id='myDiv4'>";
        m_sampleXml +=            "<div style='color:green;' id='mySubDiv1'>Green text</div>";
        m_sampleXml +=        "</div>";
        m_sampleXml +=        "<div id='myDiv5'>";
        m_sampleXml +=            "<div style='color:pink;' id='mySubDiv2'>Pink text</div>";
        m_sampleXml +=            "<div style='color:violet' id='mySubDiv3' >";
        m_sampleXml +=               "<div style='color:brown' id='mySubSubDiv1'>Brown Text</div>";
        m_sampleXml +=            "<div/>";
        m_sampleXml +=        "</div>";
        m_sampleXml +=    "</div>";	

        m_domDoc.setContent(m_sampleXml);
    }

    // Tests
    void testDoesGetElementById_mySubDiv2();
    void testDoesGetElementById_mySubDiv3();
    void testDoesGetElementByIdAsCustomAttribute_pinkStyle();
    void testDoesGetElementById_noMatch();
};


void TestFDomDocument::testDoesGetElementById_mySubDiv2()
{
    QDomElement element = m_domDoc.elementById("mySubDiv2");
    QCOMPARE(element.attribute("id"), QString("mySubDiv2"));
}

void TestFDomDocument::testDoesGetElementById_mySubDiv3()
{
    QDomElement element = m_domDoc.elementById("mySubDiv3");
    QCOMPARE(element.attribute("id"), QString("mySubDiv3"));
}

void TestFDomDocument::testDoesGetElementByIdAsCustomAttribute_pinkStyle()
{
    m_domDoc.setContent(m_sampleXml);

    //qDebug() << m_domDoc.toString();
    //QCOMPARE(m_domDoc.toString(), m_sampleXml);
    //QDomElement element = m_domDoc.elementById("mySubDiv1");

    QDomElement element = m_domDoc.elementByIdAsCustomAttribute("style", "color:pink;");
    QCOMPARE(element.attribute("id"), QString("mySubDiv2"));
    //qDebug() << "grr: " << element.attribute("id");
}

void TestFDomDocument::testDoesGetElementById_noMatch()
{
    QDomElement element = m_domDoc.elementById("No_Match");
    QCOMPARE(element.isNull(), true);
    //QCOMPARE(element.attribute("id"), QString(""));
}


QTEST_MAIN(TestFDomDocument)
#include "testfdomdocument.moc"