qDebug("MDomQuery: // query must not be empty!");
return;
}
- if(ql[0]=="*"){
- qDebug("MDomQuery: // query must not start with wildcard *.");
+ if(ql[0]=="*" || ql[0]=="@*"){
+ qDebug("MDomQuery: // query must not start with wildcard * or @*.");
return;
}
- ndlst=doc.elementsByTagName(ql[0]);
- ql.removeFirst();
+ if(ql[0].startsWith("@")){
+ qDebug("MDomQuery: cannot start with attributes in a // query.");
+ return;
+ }else{
+ ndlst=doc.elementsByTagName(ql[0]);
+ ql.removeFirst();
+ }
}else
if(path.startsWith("/")){
QDomElement root=start.ownerDocument().documentElement();
m_result<<root;
return;
}
+ if(ql[0].startsWith("@")){
+ qDebug("MDomQuery: cannot start with attributes in a / query.");
+ return;
+ }
if(ql[0]=="*"){
+ //any root
ndlst<<root;
}else{
+ //specific root
if(root.tagName()==ql[0])ndlst<<root;
}
+ //remove root from query, then go on below
ql.removeFirst();
}else{
+ //query starts at current element
ndlst<<start;
}
-
-
+ //iteratively go through path and eliminate non-matches
+ while(ql.size()>0){
+ MDomNodeList lst2;
+ //parse pattern
+ if(ql[0].startsWith("@")){
+ //attribute handling...
+ if(ql.size()>1){
+ qDebug("MDomQuery: cannot sub-parse attributes.");
+ return;
+ }
+ if(ql[0]=="@*"){
+ //get all attributes of all current elements
+ for(int i=0;i<ndlst.size();i++)
+ lst2+=ndlst[i].toElement().attributes();
+ }else{
+ //get specific attributes
+ for(int i=0;i<ndlst.size();i++){
+ QDomElement el=ndlst[i].toElement();
+ QString nm=ql[0].mid(1);
+ if(el.hasAttribute(nm))
+ lst2<<el.attributeNode(nm);
+ }
+ }
+ }else{
+ //element handling
+ QString nm=ql[0];
+ if(nm=="*"){
+ //copy any element
+ for(int i=0;i<ndlst.size();i++){
+ QDomNodeList nl=ndlst[i].childNodes();
+ for(int j=0;j<nl.size();j++){
+ QDomElement el=nl.at(j).toElement();
+ if(!el.isNull())
+ lst2<<el;
+ }
+ }
+ }else{
+ //search for specific elements
+ for(int i=0;i<ndlst.size();i++)
+ lst2+=ndlst[i].toElement().elementsByTagName(nm);
+ }
+ }
+ //next recursion:
+ ql.removeFirst();
+ ndlst=lst2;
+ }
+ m_result=ndlst;
+}
+
+QString MDomQuery::toString()const
+{
+ QString ret;
+ for(int i=0;i<m_result.size();i++){
+ if(ret!="")ret+=" ";
+ if(m_result[i].isElement())
+ ret+=m_result[i].toElement().text();
+ else
+ ret+=m_result[i].nodeValue();
+ }
+ return ret;
}
-QString MDomQuery::toString()const{}
-QStringList MDomQuery::toStringList()const{}
+QStringList MDomQuery::toStringList()const
+{
+ QStringList ret;
+ for(int i=0;i<m_result.size();i++)
+ if(m_result[i].isElement())
+ ret<<m_result[i].toElement().text();
+ else
+ ret<<m_result[i].nodeValue();
+ return ret;
+}
MDomNodeList(const MDomNodeList&l):QList<QDomNode>(l){}
MDomNodeList(const QList<QDomNode>&l):QList<QDomNode>(l){}
MDomNodeList(const QDomNodeList&l){for(int i=0;i<l.size();i++)append(l.at(i));}
+ MDomNodeList(const QDomNamedNodeMap&l){for(int i=0;i<l.size();i++)append(l.item(i));}
+
+ MDomNodeList& operator+=(const QDomNodeList&l)
+ {for(int i=0;i<l.size();i++)append(l.at(i));return *this;}
+
+ MDomNodeList& operator+=(const QDomNamedNodeMap&l)
+ {for(int i=0;i<l.size();i++)append(l.item(i));return *this;}
};
Namespaces/Prefixes are ignored. It is recommended to use patternist for cases in which namespaces matter.
-The search path uses slash "/" to separate elements, the last item in the search path may start with "@" to match an attribute instead of an element. The special names "*" and "@*" may be used to match any element or attribute. If the search path starts with a slash "/", the search starts at the document root irrespective of what element was fed to the query object (the first item matched against the root element). If the search path starts with a double slash "//" the search considers all positions in the document as valid starting points (using all elements that match the first item to start the search, the first item must not be "*" in that case). If there is no slash at the start of the path the search begins exactly at the supplied element (the first item matched against child elements of the supplied element).
+The search path uses slash "/" to separate elements, the last item in the search path may start with "@" to match an attribute instead of an element. The special names "*" and "@*" may be used to match any element or attribute. If the search path starts with a slash "/", the search starts at the document root irrespective of what element was fed to the query object (the first item matched against the root element). If the search path starts with a double slash "//" the search considers all positions in the document as valid starting points (using all elements that match the first item to start the search, the first item must not be "*" in that case). If there is no slash at the start of the path the search begins exactly at the supplied element (the first item matched against child elements of the supplied element). Queries that start with a slash must search an element at the first position.
When casting to QString or QStringList the query object uses the method text() of the QDomElement to generate the content of the element. For attributes it simply returns the value.
#include "phpout.h"
#include "qtout.h"
+#include "../src/domquery.h"
+
#include <QDir>
#include <QDomDocument>
#include <QDomElement>
m_verNeedComm="0";
m_verHR="0.0";
m_svnTarget=".";
- m_svnCache=".svn_*.xml";
+ m_svnRev="unknown uncertain";
m_svnExe="svn";
m_dbInst="dbInst";
m_dbScheme="dbScheme";
if(el2.isNull())continue;
if(el2.hasAttribute("target"))
m_svnTarget=el2.attribute("target");
- if(el2.hasAttribute("cacheFile"))
- m_svnCache=el2.attribute("cacheFile");
if(el2.hasAttribute("exe"))
m_svnExe=el2.attribute("exe");
}
qDebug("Warning: unable to parse output of svn info.");
return;
}
- //TODO: parse it.
+ //parse it.
+ QStringList rl=MDomQuery(doc.documentElement(),"/*/entry/@revision");
+ if(rl.size()==0){
+ m_svnRev="unknown";
+ }else{
+ int minv,maxv;
+ minv=maxv=rl[0].toInt();
+ for(int i=1;i<rl.size();i++){
+ int cv=rl[1].toInt();
+ if(cv<minv)minv=cv;
+ if(cv>maxv)maxv=cv;
+ }
+ if(minv==maxv)
+ m_svnRev=QString::number(maxv);
+ else
+ m_svnRev=QString::number(minv)+"-"+QString::number(maxv);
+ }
}
//svn status
svn.start(m_svnExe,QStringList()<<"status"<<"--xml"<<"--non-interactive"<<".");
svn.waitForFinished();
- if(svn.exitCode()!=0)return;
- QFile stat(m_baseDir+"/"+QString(m_svnCache).replace("*","status"));
- if(stat.open(QIODevice::WriteOnly|QIODevice::Truncate)){
- stat.write(svn.readAllStandardOutput());
- stat.close();
- qDebug("Info: wrote svn status to %s",stat.fileName().toLocal8Bit().data());
- }else
- qDebug("Warning: unable to call svn status");
+ if(svn.exitCode()!=0){
+ qDebug("Warning: error while calling svn status.");
+ m_svnRev+=" uncertain";
+ return;
+ }else{
+ QDomDocument doc;
+ if(!doc.setContent(svn.readAllStandardOutput())){
+ qDebug("Warning: unable to parse output of svn status.");
+ m_svnRev+=" uncertain";
+ return;
+ }
+ QStringList rl=MDomQuery(doc.documentElement(),"/status/target/entry/wc-status/@item");
+ bool ismod=false;
+ for(int i=0;i<rl.size();i++){
+ if(rl[i]=="unversioned" || rl[i]=="normal")continue;
+ ismod=true;
+ break;
+ }
+ if(ismod)m_svnRev+=" modified";
+ else m_svnRev+=" vanilla";
+ }
+ qDebug("Info: SVN version info: \"%s\".",m_svnRev.toAscii().data());
}
void WocProcessor::finalize()
QString verComm()const{return m_verComm;}
QString verNeedComm()const{return m_verNeedComm;}
QString verHR()const{return m_verHR;}
- QString svnCache()const{return m_svnCache;}
+ QString svnRevision()const{return m_svnRev;}
QString dbInst()const{return m_dbInst;}
QString dbScheme()const{return m_dbScheme;}
signals:
private:
QString m_baseDir,m_wobDir,m_verComm,m_verNeedComm,m_verHR;
- QString m_svnTarget,m_svnCache,m_svnExe,m_dbInst,m_dbScheme;
+ QString m_svnTarget,m_svnRev,m_svnExe,m_dbInst,m_dbScheme;
static WocProcessor*inst;
QT-=gui
QT+=xml
-SOURCES+=processor.cpp woc.cpp qtout.cpp phpout.cpp
-HEADERS+=processor.h phpout.h qtout.h
\ No newline at end of file
+SOURCES+= \
+ processor.cpp \
+ woc.cpp \
+ qtout.cpp \
+ phpout.cpp \
+ ../src/domquery.cpp
+HEADERS+= \
+ processor.h \
+ phpout.h \
+ qtout.h \
+ ../src/domquery.h
\ No newline at end of file