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"