DomElementContainer

I often write code that iterates over an XML document and performs actions on elements with some specifig tag. Usually I do it using code like the following:

for(QDomElement elem = parent.firstChildElement("tag");
                !elem.isNull();
                elem = elem.nextSiblingElement("tag")){
    doSomething(elem);
}

This is fine, but I thought it’d be nicer to do it using the foreach() loop offered by Qt. Out of the box Qt doesn’t allow to use foreach with xml documents, so I decided to do something about it :)

After 15 minutes the class was ready:

#include 
#include 
#include 

class DomElementContainer {
public:
  class const_iterator {
    friend class DomElementContainer;
  public:
      const_iterator(){}
      const_iterator &operator++(){
        m_e = m_e.nextSiblingElement(m_t);
        return *this;
      }
      const QDomElement & operator*(){
        return m_e;
      }
      bool operator==(const const_iterator &other) const {
        return (m_e==other.m_e && m_t==other.m_t);
      }
      bool operator!=(const const_iterator &other) const {
        return (m_e!=other.m_e || m_t!=other.m_t);
      }
  private:
      const_iterator(const QDomElement &e, const QString &t){
        m_e = e;
        m_t = t;
      }
      QDomElement m_e;
      QString m_t;
  };

  DomElementContainer(const QDomElement &e, const QString &tag=QString::null){
    m_tag = tag;
    m_elem = e;
  }
  DomElementContainer(const QDomDocument &d, const QString &tag=QString::null){
    m_tag = tag;
    m_elem = d.documentElement();
  }
  const_iterator begin() const{
    return const_iterator(m_elem.firstChildElement(m_tag), m_tag);
  }
  const_iterator end() const {
    return const_iterator(QDomElement(), m_tag);
  }
private:
  QDomElement m_elem;
  QString m_tag;
};

Now it’s possible to do the following:

#include "domelementcontainer.h"

const char *xml = "content 1content 2 "
                  "wrongcontent"
                  "content 3";

int main(){
    QDomDocument doc;
    doc.setContent(QString(xml));
    DomElementContainer c(doc, "tag");
    foreach(QDomElement e, c)
      qDebug("%s", qPrintable(e.text()));
    return 0;
}

Download available here.

Leave a Reply