DOM Xerces类库使用方法
生活随笔
收集整理的這篇文章主要介紹了
DOM Xerces类库使用方法
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
DOM Xerces類(lèi)庫(kù)使用方法
Tuxedo中XML的歷史如 今隨著XML逐漸成為主流的數(shù)據(jù)格式之一,自然而然地 Tuxedo將之作為一種基本緩沖類(lèi)型予以支持。 Tuxedo 7.1 引入了XML緩沖類(lèi)型,但迄今為止對(duì)于Tuxedo中的XML并無(wú)較多的論述。Tuxedo 7.1中并未攜帶真正的XML API,因?yàn)橥ǔUJ(rèn)為將開(kāi)發(fā)人員自己最喜歡的DOM或SAX實(shí)現(xiàn)合并到其應(yīng)用程序中是其自身的責(zé)任。
現(xiàn)在,由于在Tuxedo內(nèi)嵌了Xerces 1.7 版本(來(lái)自Apache XML項(xiàng)目)庫(kù),所以伴隨Tuxedo 8.1提供了一套真正的XML API。8.1版本還包含了一個(gè)稱(chēng)為xmlstockapp(xml股票程序)的XML示例。
這一點(diǎn)為開(kāi)發(fā)人員增加了許多XML功能,例如XML解析,XML樹(shù)遍歷或構(gòu)建,以及XML格式化,從而不需要使用外部的產(chǎn)品。何為XML?
XML經(jīng)常作為一種“語(yǔ)言”被提及,然而它實(shí)際上是一種用于描述文本緩沖區(qū)中的層次結(jié)構(gòu)數(shù)據(jù)集的標(biāo)準(zhǔn)格式。這種數(shù)據(jù)格式可以通過(guò)一種加強(qiáng)數(shù)據(jù)結(jié)構(gòu)和層次關(guān)系的本地語(yǔ)法(稱(chēng)為DTD)來(lái)進(jìn)行控制。我如何在XML中進(jìn)行編碼?
XML并非一種語(yǔ)言,而是一種數(shù)據(jù)格式。編碼意味著使用一種API,從一個(gè)純文本緩沖區(qū)到數(shù)據(jù)樹(shù)來(lái)回進(jìn)行數(shù)據(jù)轉(zhuǎn)換,或者對(duì)數(shù)據(jù)樹(shù)進(jìn)行遍歷或操縱。想要了解如何使用XML進(jìn)行編碼,請(qǐng)參看下文“……一般任務(wù)”一節(jié)。有哪些可用的API對(duì)XML進(jìn)行操縱作?
目前存在數(shù)種標(biāo)準(zhǔn)API對(duì)XML進(jìn)行操縱,最著名的是DOM,SAX和XPATH。所有的API都針對(duì)不同語(yǔ)言具有不同的實(shí)現(xiàn),但是本文僅僅關(guān)注Tuxedo 8.1產(chǎn)品中包含的Xerces的C/C 實(shí)現(xiàn)。我應(yīng)在何時(shí)使用XML?
由于XML是一種標(biāo)準(zhǔn)的有組織的格式,如今它已經(jīng)成為一種廣為使用的便利格式來(lái)在不同系統(tǒng)間進(jìn)行數(shù)據(jù)交換。即使結(jié)構(gòu)上(DTD)略作改動(dòng)來(lái)添加一些子節(jié)點(diǎn)或新屬性,XML的自描述性和結(jié)構(gòu)化的方式也有助于數(shù)據(jù)的理解。XML也是易于閱讀的,而二進(jìn)制數(shù)據(jù)則不然。
然而XML仍具有一些缺點(diǎn):
- 它使您的數(shù)據(jù)大幅膨脹(每個(gè)域?qū)⒃黾右粋€(gè)20字節(jié)左右的標(biāo)題,并且所有的二進(jìn)制域?qū)U(kuò)大為相應(yīng)的字符串表達(dá))。
- 在進(jìn)行解析和格式化時(shí)它增加了CPU的開(kāi)銷(xiāo),尤其是在解析和檢驗(yàn)文檔是否是“格式良好”時(shí)。
- 其API均比較復(fù)雜。
這些任務(wù)并非只針對(duì)Tuxedo,而是適用于所有使用DOM處理XML數(shù)據(jù)的程序。
初始化Xerces
一旦您希望使用Xerces API進(jìn)行工作就必須強(qiáng)制進(jìn)行初始化:
| /* initialise xerces */ try { ??? XMLPlatformUtils::Initialize (); } catch (const XMLException & toCatch) { ??? char *pMsg = XMLString::transcode (toCatch.getMessage ()); ??? userlog ("Error during Xerces-c Initialization.\n" ??????????? "?? Exception message: %s", pMsg); ??? delete[]pMsg; ??? return -1; } |
當(dāng)XML 數(shù)據(jù)被接收時(shí),它通常是一個(gè)文本緩沖區(qū)或一個(gè)文件。DOM API是一種用于處理數(shù)據(jù)節(jié)點(diǎn)樹(shù)的API,這種節(jié)點(diǎn)樹(shù)通常由包含了屬性和其他元素的元素構(gòu)成。一個(gè)程序可以通過(guò)遞歸掃描元素節(jié)點(diǎn)來(lái)遍歷DOM樹(shù)。
如果一個(gè)程序希 望通過(guò)層次結(jié)構(gòu),元素名稱(chēng)或者屬性來(lái)訪(fǎng)問(wèn)緩沖區(qū)內(nèi)的數(shù)據(jù),該緩沖區(qū)首先需要被讀入并轉(zhuǎn)化為一棵數(shù)據(jù)樹(shù)。這一過(guò)程被稱(chēng)為解析。要執(zhí)行文本解析您需要實(shí)現(xiàn)一個(gè) 來(lái)源類(lèi)(LocalFileInputSource或MemBufInputSource)來(lái)容納將要解析的文本,并使用DOMParser的實(shí)現(xiàn)來(lái)進(jìn)行 解析。
| #include <xercesc/util/PlatformUtils.hpp> #include <xercesc/framework/XMLFormatter.hpp> #include <xercesc/util/XMLString.hpp> #include <xercesc/util/XMLUniDefs.hpp> #include <xercesc/framework/MemBufInputSource.hpp> #include <xercesc/framework/LocalFileInputSource.hpp>#include <xercesc/parsers/DOMParser.hpp> #include <xercesc/dom/DOM_Node.hpp>/* parse a XML file */ char *xmlFileName = "./myfile.xml"; DOMParser *parser = 0; DOM_Document document; DOM_Element topLevel;LocalFileInputSource source (XMLString::transcode (xmlFileName)); // //?? Create our parser, then set the parsing options. //?? discovers errors during the course of parsing the XML document. // parser = new DOMParser (); parser->setValidationScheme (DOMParser::Val_Never); parser->setDoNamespaces (false); parser->setDoSchema (false); parser->setValidationSchemaFullChecking (false); parser->setCreateEntityReferenceNodes (false); parser->setToCreateXMLDeclTypeNode (true); // //?? Parse the XML file, catching any XML exceptions that might propagate //?? out of it. // try?? { ??? parser->parse (source); ??? int errorCount = parser->getErrorCount (); ??? if (errorCount > 0)?????? { ?????? printf("%d error(s) occured during parsing config\n", errorCount); ?????? goto clean; ????? } } catch (const XMLException & e)?? { ??? printf("An error occured during parsing \n??? Message: %s\n" ?????????? "", e.getMessage ()); ??? goto clean; } catch (const DOM_DOMException & e)?? { ??? printf("A DOM error occured during parsing config\n" ??????????? "Exception code: %d\n", e.code); ??? goto clean; } catch (...)?? { ??? printf ("An error occured during parsing config\n"); ??? goto clean; } … |
一旦遇到解析錯(cuò)誤,獲取錯(cuò)誤發(fā)生的行號(hào)和列號(hào)來(lái)代替僅僅進(jìn)行錯(cuò)誤計(jì)數(shù)(或獲取一個(gè)致命異常)是更好的方式。這種做法能夠通過(guò)安裝錯(cuò)誤處理來(lái)輕松實(shí)現(xiàn):
| #include <xercesc/sax/ErrorHandler.hpp> class ExampleErrorHandler: public ErrorHandler { ??? virtual void anyError(char* type, const SAXParseException& exception) ; public: ??? /** Default constructor */ ??? ExampleErrorHandler(){}; ??? /** Destructor */ ??? ~ExampleErrorHandler() {}; ??? void warning(const SAXParseException& exception){anyError("warning", exception); }; ??? void error(const SAXParseException& exception) {anyError("error", exception); }; ??? void fatalError(const SAXParseException& exception){anyError("fatal error", exception); }; ??? void resetErrors() {}; };void ExampleErrorHandler::anyError(char* type, const SAXParseException& exception){ ?????? printf("Parser %s line %d column %d: %ls %ls : %ls", type, ????????????? exception.getLineNumber () , ????????????? exception.getColumnNumber () , ????????????? exception.getPublicId?? () , ????????????? exception.getSystemId () , ????????????? exception.getMessage ()); } |
| ExampleErrorHandler handler; parser = new DOMParser (); parser->setErrorHandler(&handler); // //?? Parse the XML file, catching any XML exceptions that might propagate //?? out of it. // try?? { ??? parser->parse (source); } … |
您可以按這種方式創(chuàng)建一棵DOM樹(shù)。它創(chuàng)建了根元素。
| /* creates an empty dom tree */ DOM_DOMImplementation impl; DOM_Document doc = impl.createDocument (0,?? // root element namespace URI. ???????????????????????????????????? rootname,?? // root element name ???????????????????????????????????? DOM_DocumentType ());// document type object (DTD). /* fetch the root element */ DOM_Element rootElem = doc.getDocumentElement (); |
| //Add new (empty) Element to the root element ????? DOM_Element parentNode = …;// parent is known ????? DOM_Element prodElem = doc->createElement (tagName); ????? parentNode->appendChild (prodElem); |
| parentNode->removeChild (prodElem); |
一旦元素被創(chuàng)建您就不可以修改其標(biāo)簽名稱(chēng)。
遍歷一個(gè)元素的子元素
既然您已經(jīng)創(chuàng)建了一個(gè)XML元素節(jié)點(diǎn),您(可能)希望訪(fǎng)問(wèn)其子元素:
| DOM_Element parent = …; // parent is known DOM_Node child; child = parent.getFirstChild (); while?? (child != 0)???? { ??? //work with child?? ??? … ??? //pickup next child ??? child?? = child.getNextSibling (); } |
您可能希望忽略某些節(jié)點(diǎn),在這種情況下,檢查節(jié)點(diǎn)類(lèi)型:
| switch (child.getNodeType ()) ?????? { ?????? case DOM_Node::ELEMENT_NODE: ???????????? … ???????? break; ?????? case DOM_Node::ATTRIBUTE_NODE: ???????????? … ???????? break; ?????? case DOM_Node::TEXT_NODE: ???????????? … ???????? break; ?????? case DOM_Node::CDATA_SECTION_NODE: ???????????? … ???????? break; ?????? case DOM_Node::ENTITY_REFERENCE_NODE: ???????????? … ???????? break; ?????? case DOM_Node::ENTITY_NODE: ???????????? … ???????? break; ?????? case DOM_Node::PROCESSING_INSTRUCTION_NODE: ???????????? … ???????? break; ?????? case DOM_Node::COMMENT_NODE: ???????????? … ???????? break; ?????? case DOM_Node::DOCUMENT_NODE: ???????????? … ???????? break; ?????? case DOM_Node::DOCUMENT_TYPE_NODE: ???????????? … ???????? break; ?????? case DOM_Node::DOCUMENT_FRAGMENT_NODE: ???????????? … ???????? break; ?????? case DOM_Node::NOTATION_NODE: ???????????? … ???????? break; ?????? case DOM_Node::XML_DECL_NODE: ???????????? … ???????? break; ?????? default: ???????????? … ?????? } |
一個(gè)元素內(nèi)的值存儲(chǔ)在一個(gè)文本子節(jié)點(diǎn)中:
| DOM_Element parent = …; // parent is known DOM_Node child; DOM_Text value; child = parent.getFirstChild (); while?? (child != 0)???? { ??? //work with child?? ??? if (child.getNodeType () == DOM_Node::TEXT_NODE)???? { ????? value = (DOM_Text &) child; ????? break; ??? }?????? ??? //pickup next child ??? child?? = child.getNextSibling (); } DOMString unicodeValue = value.getData (); //if you need the ascii value char* asciiValue = unicodeValue.transcode (); //work with your value … //free the value delete []asciiValue ; |
另外,如果存在的話(huà),不要忘記刪除之前的值:
| DOM_Element parent = …; // parent is known DOM_Node child; DOM_Text value; bool childFound = false; child = parent.getFirstChild (); while?? (child != 0)???? { ??? //work with child?? ??? if (child.getNodeType () == DOM_Node::TEXT_NODE)???? { ????? value = (DOM_Text &) child; ????? childFound = true; ????? break; ??? }?? ??? //pickup next child ??? child?? = child.getNextSibling (); } //now , maybe create a text node if (!childFound) { ???????? value = doc->createTextNode (); ???????? parent.appendChild (value); } DOMString unicodeValue(asciiValue); value.setData(unicodeValue); |
要添加(或設(shè)置)一個(gè)元素屬性的值,使用以下方法:
| DOMString unicodename(asciiname); ????? DOMString unicodevalue(asciivalue); ????? DOM_Element element = …;// element is known ????? //Add new attribute to the element ????? element->setAttribute(unicodename, unicodevalue); |
要?jiǎng)h除一個(gè)元素的屬性,使用以下方法: [I.L.H1]??
| DOMString unicodename(asciiname); ????? DOM_Element element = …;// element is known ????? //Add new attribute to the element ????? element->removeAttribute(unicodename); |
要瀏覽一個(gè)元素的所有屬性,您可以按以下方法加以實(shí)現(xiàn):
| //loop through this element attributes and fill the config structure ????? DOMString unicodename; ????? DOMString unicodevalue; ????? DOM_NamedNodeMap attributes; ????? DOM_Element element = …;// element is known ????? attributes = element.getAttributes (); ????? int attrCount; ????? attrCount = attributes.getLength (); ????? for (i = 0; i < attrCount; i )???? { ????????? DOM_Node attribute = attributes.item (i); ????????? //work with the attribute ????????? unicodename = attribute.getNodeName (); ????????? unicodevalue= attribute. getNodeValue (); ????????? //if need ascii values, get them ????????? char* asciiname= unicodename.transcode (); ????????? char* asciivalue = unicodevalue.transcode (); ????????? … ????????? //but don't forget to release them ????????? delete []asciiname; ????????? delete []asciivalue; ????? } |
并沒(méi)有直接的方法來(lái)將DOM樹(shù)格式化為XML文本緩沖區(qū)。最簡(jiǎn)單的方法是參考Xerces 1.7中DOMPrint的示例,或者查看一下本文附帶的XFML庫(kù)中的XMLimplementation.hxx文件。
具體的想法是實(shí)現(xiàn)一個(gè)函數(shù),該函數(shù)將遍歷所有節(jié)點(diǎn)并將節(jié)點(diǎn)及其屬性打印輸出。
Tuxedo中的XML示例:
所有附帶的代碼示例均經(jīng)過(guò)編譯,并在Microsoft Windows NT下使用。由于示例中依賴(lài)的庫(kù)均已在Unix中經(jīng)過(guò)編譯,移植到Unix的工作量應(yīng)該很小。
轉(zhuǎn)載于:https://blog.51cto.com/panpan/187272
總結(jié)
以上是生活随笔為你收集整理的DOM Xerces类库使用方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 七招挽回受损WORD文档
- 下一篇: 开源游戏引擎详解