<?xml version="1.0" encoding="windows-1251"?><ED EDNo="805253" EDDate="2005-03-01" EDAuthor="4552000000"/>
// объект CED ed;// 1. чтение документа (инициализация реквизитов объекта)ed.readDocument(fileName);// 2. изменение реквизитовed.EDNo = "1";ed.EDDate = "2010-03-22";ed.EDAuthor = "4552000001";// 3. запись измененого XML-документаed.writeDocument(fileName);
<?xml version="1.0" encoding="windows-1251"?><ED EDNo="1" EDDate="2010-03-22" EDAuthor="4552000001"/>
// cnode.h#ifndef CNODE_H#define CNODE_H#include <QString>//----------------------------------------------------------------------// CNode - узел объекта// Интерфейсный класс, обеспечивающий взаимодействие объекта и XML//----------------------------------------------------------------------// Forward Declsclass QXmlAttributes;class QXmlStreamWriter;class QIODevice;class CNode{private: // вспомогательные методы работы с устройствами записи/чтения bool writeToDevice(QIODevice* device); bool readFromDevice(QIODevice* device);protected: // пространство имен и префикс элемента QString nodeNamespace; QString nodePrefix; // методы для записи в XML необязательных реквизитов void writeAttribute(QXmlStreamWriter& writer,const QString& name, const QString& value); void writeTextElement(QXmlStreamWriter& writer,const QString& nsUri,const QString& name,const QString& text); // интерфейсные методы - используются для чтения из XML SAX-парсером friend class CSaxHandler; virtual void setRequisites(const QString &name,const QXmlAttributes &attributes); virtual CNode* getNode(const QString &name); virtual bool isTextElement(const QString &name); // интерфейсный метод - запись объекта в XML virtual bool writeNode(QXmlStreamWriter& writer,const QString& nsUri);public: CNode(); // наименование узла QString nodeName; // чтение объекта из XML - из файла или символьного массива bool readDocument(const QString &fileName); bool readDocument(QByteArray* array); // запись объекта в XML - в файл или символьный массив bool writeDocument(const QString &fileName); bool writeDocument(QByteArray* array); // флаги, используемые при записи static QString encoding; // кодировка, используемая при записи static bool autoFormatting; // флаг форматирования XML при записи};//----------------------------------------------------------------------#endif // CNODE_H
// cnode.cpp#include "cnode.h"#include "cnode.h"#include "csaxhandler.h"#include <QFile>#include <QBuffer>#include <QXmlStreamWriter>//----------------------------------------------------------------------QString CNode::encoding = "WINDOWS-1251";bool CNode::autoFormatting = true;//----------------------------------------------------------------------CNode::CNode(){}//----------------------------------------------------------------------// интерфейсные методы//----------------------------------------------------------------------void CNode::setRequisites(const QString &name,const QXmlAttributes &attributes){ // ничего не делается - для классов, не содержащих реквизиты}// указатель на узел элементCNode* CNode::getNode(const QString &name){ if(name==nodeName) return this; else return 0;}// проверка, является ли элемент текстовымbool CNode::isTextElement(const QString &name){ return false;}bool CNode::writeNode(QXmlStreamWriter& writer,const QString& nsUri){ return true;}//----------------------------------------------------------------------// запись необязательных реквизитов ЭС//----------------------------------------------------------------------void CNode::writeAttribute(QXmlStreamWriter& writer,const QString& name, const QString& value){ if(!value.isEmpty()) writer.writeAttribute(name, value);}void CNode::writeTextElement(QXmlStreamWriter& writer,const QString& nsUri,const QString& name,const QString& text){ if(!text.isEmpty()) writer.writeTextElement(nsUri,name,text);}//----------------------------------------------------------------------// чтение из XML (при совпадении типов документа и объекта)//----------------------------------------------------------------------bool CNode::readDocument(const QString &fileName){ QFile device(fileName); return readFromDevice(&device);}bool CNode::readDocument(QByteArray* array){ QBuffer device(array); return readFromDevice(&device);}bool CNode::readFromDevice(QIODevice* device){ if(!device->open(QIODevice::ReadOnly | QIODevice::Text)) return false; QXmlInputSource xmlInputSource(device); CSaxHandler handler(this); QXmlSimpleReader reader; reader.setContentHandler(&handler); bool ok=reader.parse(xmlInputSource); device->close(); return true;}//----------------------------------------------------------------------// запись в XML//----------------------------------------------------------------------bool CNode::writeDocument(const QString &fileName){ QFile device(fileName); return writeToDevice(&device);}bool CNode::writeDocument(QByteArray* array){ array->clear(); QBuffer device(array); return writeToDevice(&device);}bool CNode::writeToDevice(QIODevice* device){ QXmlStreamWriter writer(device); if(!device->open(QIODevice::WriteOnly)) return false; writer.setAutoFormatting(autoFormatting); // формирование xml-документа writer.setCodec(encoding.toAscii().data()); writer.writeStartDocument(); if(!nodeNamespace.isEmpty()) writer.writeNamespace(nodeNamespace, nodePrefix); // вызов виртуального метода writeNode(writer,nodeNamespace); writer.writeEndDocument(); device->close(); return true;}
// csaxhandler.h#ifndef CSAXHANDLER_H#define CSAXHANDLER_H#include <QXmlDefaultHandler>#include <QStack>//----------------------------------------------------------------------// обработчики для SAX-парсера//----------------------------------------------------------------------class CNode;class CSaxHandler : public QXmlDefaultHandler{private: CNode* doc; // указатель на объект QStack<CNode*> nodeStack; // стек обрабатываемых элементов QString textElement; // буфер содержимого текстового элемента QString encoding; // кодировка документаpublic: CSaxHandler(); CSaxHandler(CNode* node); virtual ~CSaxHandler(); // связывание объекта с обработчиками void setDocument(CNode* node); void reset(); // очистить стек и буферы // обработчики bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes); bool characters(const QString &str); bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);};//----------------------------------------------------------------------#endif // CSAXHANDLER_H
// csaxhandler.cpp#include "csaxhandler.h"#include "cnode.h"//----------------------------------------------------------------------CSaxHandler::CSaxHandler(){ reset();}CSaxHandler::CSaxHandler(CNode* node){ setDocument(node);}CSaxHandler::~CSaxHandler(){ // doc не удаляем (владелец - внешняя программа)! textElement.clear(); nodeStack.clear();}void CSaxHandler::reset(){ doc=0; textElement.clear(); nodeStack.clear();}void CSaxHandler::setDocument(CNode* node){ reset(); doc=node; // корневой элемент nodeStack.push(doc);}//----------------------------------------------------------------------bool CSaxHandler::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes){ if(nodeStack.isEmpty()) return false; // текущий элемент CNode* node=nodeStack.top(); // обрабатываемый элемент if(node) node=node->getNode(localName); // инициализация реквизитов if(node) node->setRequisites(localName,attributes); // сделаем его текущим nodeStack.push(node); textElement.clear(); return true;}//----------------------------------------------------------------------bool CSaxHandler::characters(const QString &str){ textElement+=str; return true;}//----------------------------------------------------------------------bool CSaxHandler::endElement(const QString &namespaceURI, const QString &localName, const QString &qName){ if(nodeStack.isEmpty()) return false; CNode* node=nodeStack.top(); // инициализация текстовых элементов if(node && node->isTextElement(localName)){ QXmlAttributes textAttr; textAttr.append(localName,"","",textElement); node->setRequisites(localName,textAttr); } // элемент обработан nodeStack.pop(); return true;}
<?xml version="1.0" encoding="WINDOWS-1251"?><ED201 xmlns="urn:cbr-ru:ed:v2.0" CtrlCode="0999" CtrlTime="10:13:37" EDNo="805253" EDDate="2010-03-24" EDAuthor="4552000000"> <Annotation>Ошибка при обработке ЭС</Annotation> <EDRefID EDNo="1000" EDDate="2010-03-24" EDAuthor="4525545000"/></ED201>
// cbr_ed201.h#ifndef cbr_ed201H#define cbr_ed201H#include "cnode.h"//----------------------------------------------------------------------// EDRefIDclass CEDRefID : public CNode{protected: virtual void setRequisites(const QString &name,const QXmlAttributes &attributes);public: virtual bool writeNode(QXmlStreamWriter& writer,const QString& nsUri); CEDRefID(); // Methods & Properties QString EDNo; QString EDDate; QString EDAuthor;};//----------------------------------------------------------------------// ED201 class CED201 : public CEDRefID{private: virtual void setRequisites(const QString &name,const QXmlAttributes &attributes); virtual CNode* getNode(const QString &name); virtual bool isTextElement(const QString &name); virtual bool writeNode(QXmlStreamWriter& writer,const QString& nsUri);public: CED201(); // Methods & Properties QString CtrlCode; QString CtrlTime; QString Annotation; CEDRefID EDRefID;};//----------------------------------------------------------------------#endif
// cbr_ed201.cpp#include "cbr_ed201.h"#include <QXmlAttributes>#include <QXmlStreamWriter>//----------------------------------------------------------------------// EDRefIDCEDRefID::CEDRefID(){ // пространство имен nodeNamespace = "urn:cbr-ru:ed:v2.0"; nodePrefix = "ed";}
// инициализация реквизитов документа при чтении ЭДvoid CEDRefID::setRequisites(const QString &,const QXmlAttributes &attributes){ EDNo=attributes.value("EDNo"); EDDate=attributes.value("EDDate"); EDAuthor=attributes.value("EDAuthor");}
bool CEDRefID::writeNode(QXmlStreamWriter& writer,const QString& nsUri){ writer.writeStartElement(nsUri,nodeName); writer.writeAttribute("EDNo", EDNo); writer.writeAttribute("EDDate", EDDate); writer.writeAttribute("EDAuthor", EDAuthor); writer.writeEndElement(); return true;}
// ED201CED201::CED201(){ nodeName="ED201"; EDRefID.nodeName="EDRefID";}
// инициализация реквизитов документа при чтении ЭДvoid CED201::setRequisites(const QString &name,const QXmlAttributes &attributes){ if(name=="Annotation") Annotation=attributes.value(name); else{ // инициализация реквизитов базового класса CEDRefID::setRequisites(name,attributes); CtrlCode=attributes.value("CtrlCode"); CtrlTime=attributes.value("CtrlTime"); }}
CNode* CED201::getNode(const QString &name){ if(name==nodeName || name=="Annotation") return this; else if(name=="EDRefID") return &EDRefID; else return 0;}
bool CED201::isTextElement(const QString &name){ return (name=="Annotation");}
bool CED201::writeNode(QXmlStreamWriter& writer,const QString& nsUri){ writer.writeStartElement(nsUri,nodeName); writer.writeAttribute("EDNo", EDNo); writer.writeAttribute("EDDate", EDDate); writer.writeAttribute("EDAuthor", EDAuthor); writer.writeAttribute("CtrlCode", CtrlCode); writer.writeAttribute("CtrlTime", CtrlTime); writer.writeTextElement(nsUri,"Annotation", Annotation); EDRefID.writeNode(writer,nsUri); writer.writeEndElement(); return true;}
writer.writeAttribute("EDNo", EDNo);
writeAttribute(writer, "EDNo", EDNo);
<ED201 xmlns="urn:cbr-ru:ed:v2.0" CtrlCode="0999" CtrlTime="10:13:37" EDNo="805253" EDDate="2010-03-24" EDAuthor="4552000000"> <Annotation>Ошибка при обработке ЭС</Annotation> <EDRefID EDNo="1000" EDDate="2010-03-24" EDAuthor="4525545000"/></ED201>
void MainWindow::xmlSlot(){ QByteArray in; QString text=textEdit->toPlainText(); in.append(text); // 1. чтение XML-документа CED201 ed; ed.readDocument(&in); // 2. работа с реквизитами ed.EDNo = "1"; ed.EDDate = "2010-03-01"; ed.EDAuthor = "4552000001"; // 3. запись XML-документа QByteArray out; ed.writeDocument(&out); textEdit->append(""); textEdit->append(out);}
<?xml version="1.0" encoding="windows-1251"?><ed:ED201 xmlns:ed="urn:cbr-ru:ed:v2.0" EDNo="1" EDDate="2010-03-01" EDAuthor="4552000001" CtrlCode="0999" CtrlTime="10:13:37"> <Annotation>Ошибка при обработке ЭС</Annotation> <EDRefID EDNo="1000" EDDate="2010-03-24" EDAuthor="4525545000"/></ed:ED201>
<?xml version="1.0" encoding="WINDOWS-1251"?><ED232 xmlns="urn:cbr-ru:ed:v2.0" EDAuthor="4525000000" EDDate="2008-03-14" EDNo="1005"> <PLAN BS="10101" RKC="2" Type="2"/> <PLAN BS="10207" RKC="1" Type="2"/> <PLAN BS="10208" RKC="1" Type="2"/></ED232>
class CPLAN;typedef QVector<CPLAN *> CPLANList;class CED232 : public CED{private: virtual CNode* getNode(const QString &name); virtual bool writeNode(QXmlStreamWriter& writer,const QString& nsUri);public: CED232(); ~CED232(); CEDRefID InitialED; CPLANList PLAN;};
CED232::~CED232(){ for(int i=0; i<PLAN.size(); i++) delete PLAN[i];}
CNode* CED232::getNode(const QString &name){ if(name==nodeName) return this; else if(name=="PLAN"){ CPLAN* info=new CPLAN(); PLAN.push_back(info); return info; }else return 0;}//----------------------------------------------------------------------bool CED232::writeNode(QXmlStreamWriter& writer,const QString& nsUri){ writer.writeStartElement(nsUri,nodeName); writer.writeAttribute("EDNo", EDNo); writer.writeAttribute("EDDate", EDDate); writer.writeAttribute("EDAuthor", EDAuthor); for(int i=0; i<PLAN.size(); i++) PLAN[i]->writeNode(writer,nsUri); writer.writeEndElement(); return true;}
C++ (Qt) virtual void setRequisites(const QString &name,const QXmlAttributes &attributes); virtual bool writeNode(QXmlStreamWriter& writer,const QString& nsUri); virtual CNode* getNode(const QString &name);
bool CSaxHandler::endElement(const QString &namespaceURI, const QString &localName, const QString &qName){ if(nodeStack.isEmpty()) return false; CNode* node=nodeStack.top(); // инициализация текстовых элементов if(node && textElement.trimmed().length()){ QXmlAttributes textAttr; textAttr.append(localName,"","",textElement); node->setRequisites(localName,textAttr); textElement.clear(); } // элемент обработан nodeStack.pop(); return true;}
<?xml version="1.0"?><CHAPTER cnumber="1"> <VERS vnumber="1">Содержание текстового элемента</VERS></CHAPTER>
class CVERS : public CNode{protected: virtual void setRequisites(const QString &name,const QXmlAttributes &attributes); virtual CNode* getNode(const QString &name); virtual bool writeNode(QXmlStreamWriter& writer,const QString& nsUri);public: CVERS(); QString vnumber; QString VERS; // текстовый элемент};
void CVERS::setRequisites(const QString &name,const QXmlAttributes &attributes){ // проверка отсутствия текстового реквизита if(attributes.value("VERS").isEmpty()){ vnumber=attributes.value("vnumber"); } else // присвоение текстового элемента VERS=attributes.value(name);}//----------------------------------------------------------------------bool CVERS::writeNode(QXmlStreamWriter& writer,const QString& nsUri){ writer.writeStartElement(nsUri,nodeName); writer.writeAttribute("vnumber", vnumber); writer.writeCharacters(VERS); writer.writeEndElement(); return true;}