<PTNOID_ID OID="1" IDDst="1943" IDSrc="0"/>此节点在<LastCrossInfo>节点中,且是多个,我们遍历并读取每个节点的属性值。
class ICallBack { static const int AttributeArrayWidth = 5; static const int LocalNameIndex = 0; static const int PrefixIndex = 1; static const int URIIndex = 2; static const int ValueIndex = 3; static const int EndIndex = 4; public: virtual void startElementLocalName( const xmlChar* localname, const xmlChar* prefix, const xmlChar* URI, int nb_namespaces, const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** attributes) = 0; };这里定义了一系列的常量,这个表示的是attributes的结构,attributes一共有五(AttributeArrayWidth)项,分别存储LocalName,Prefix,URI,Value和End字段,没有的字段则为空。
static xmlSAXHandler _saxHandlerStruct = { NULL, /* internalSubset */ NULL, /* isStandalone */ NULL, /* hasInternalSubset */ NULL, /* hasExternalSubset */ NULL, /* resolveEntity */ NULL, /* getEntity */ NULL, /* entityDecl */ NULL, /* notationDecl */ NULL, /* attributeDecl */ NULL, /* elementDecl */ NULL, /* unparsedEntityDecl */ NULL, /* setDocumentLocator */ NULL, /* startDocument */ NULL, /* endDocument */ NULL, /* startElement*/ NULL, /* endElement */ NULL, /* reference */ NULL, /* characters */ NULL, /* ignorableWhitespace */ NULL, /* processingInstruction */ NULL, /* comment */ NULL, /* warning */ NULL, /* error */ NULL, /* fatalError //: unused error() get all the errors */ NULL, /* getParameterEntity */ NULL, /* cdataBlock */ NULL, /* externalSubset */ XML_SAX2_MAGIC, /* initialized */ NULL, /* private */ startElementNsHandler, /* startElementNs */ NULL, /* endElementNs */ NULL, /* serror */ };如上,可以注册很多回调函数,对应不同事件,我们进注册了startElementNsHandler对应 节点开始 这个事件。
static void startElementHandler( void* ctx, const xmlChar* localname, const xmlChar* prefix, const xmlChar* URI, int nb_namespaces, const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** attributes) { ICallBack* pCallback = (ICallBack*)ctx; pCallback ->startElementLocalName(localname, prefix, URI, nb_namespaces, namespaces, nb_attributes, nb_defaulted, attributes); }
OIDCallBack*pDO = new OIDCallBack(); try { xmlDocPtr pDoc = xmlSAXParseFileWithData( &_saxHandlerStruct, "PtnScript2_1.xml", 1, pDO); } catch (...){ }如上,我们将OIDCallBack的指针传入了xmlSAXParaseFileWithData函数,那么在解析过程中局可以使用此指针了。
class OIDCallBack : public ICallBack { public: virtual void startElementLocalName( const xmlChar* localname, const xmlChar* prefix, const xmlChar* URI, int nb_namespaces, const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** attributes) { string sOId, sDId, sSId; try { if (xmlStrcmp(localname, (const xmlChar *)"PTNOID_ID")) { return; } else { for (int i = 0; i < nb_attributes; ++i) { if (0 == xmlStrcmp(attributes[ AttributeArrayWidth * i + LocalNameIndex], (const xmlChar *)"OID")) { sOId = string(attributes[ AttributeArrayWidth * i + ValueIndex],attributes[ AttributeArrayWidth * i + EndIndex]); } else if (0 == xmlStrcmp(attributes[ AttributeArrayWidth * i + LocalNameIndex], (const xmlChar *)"IDDst")) { sDId = string(attributes[ AttributeArrayWidth * i + ValueIndex],attributes[ AttributeArrayWidth * i + EndIndex]); } else if (0 == xmlStrcmp(attributes[ AttributeArrayWidth * i + LocalNameIndex], (const xmlChar *)"IDSrc")) { sSId = string(attributes[ AttributeArrayWidth * i + ValueIndex],attributes[ AttributeArrayWidth * i + EndIndex]); } else { return; } } } } catch (...) { return; } } };
bool QueryAttributeString(const xmlNodePtr pNode, const string &sName, string &sAttribute) { if (sName.empty()) { return false; } if (NULL == pNode) { return false; } // 获取节点属性 xmlChar *pChar = xmlGetProp(pNode, (const xmlChar *)sName.c_str()); if (NULL == pChar) { return false; } sAttribute.assign((const char *)pChar); // 释放字符串内存 xmlFree(pChar); return true; } void Test_DOMParser() { boost::timer oTimer; oTimer.restart(); int iCount = 0; try { xmlDocPtr pDoc = xmlParseFile("PtnScript2_1.xml"); if (NULL == pDoc) { return; } xmlNodePtr pRoot = xmlDocGetRootElement(pDoc); if (NULL == pRoot) { return; } xmlNodePtr pLastCrossInfo = pRoot->xmlChildrenNode; // 遍历子节点 bool bFind = false; while (NULL != pLastCrossInfo) { // 比较节点名称 if ((!xmlStrcmp(pLastCrossInfo->name, (const xmlChar *)"LastCrossInfo"))) { bFind = true; break; } pLastCrossInfo = pLastCrossInfo->next; } if (!bFind) { return; } xmlNodePtr pChild = pLastCrossInfo->xmlChildrenNode; // 遍历子节点 while (NULL != pChild) { // 比较节点名称 if ((!xmlStrcmp(pChild->name, (const xmlChar *)"PTNOID_ID"))) { string sOId, sDId, sSId; if (!QueryAttributeString(pChild, "OID", sOId) || !QueryAttributeString(pChild, "IDDst", sDId) || !QueryAttributeString(pChild, "IDSrc", sSId)) { break; } ++iCount; } pChild = pChild->next; } } catch (...) { return; } cout << "Test_DOMParser: " << " Node(" << iCount << ") " << oTimer.elapsed() << endl; cout << endl; }
libxml2的SAX和DOM模式解析文件的效率实测,布布扣,bubuko.com
原文:http://blog.csdn.net/play_fun_tech/article/details/20064397