$treeview $search $mathjax $extrastylesheet
otsdaq
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 00002 #include "otsdaq-core/XmlUtilities/XmlDocument.h" 00003 #include "otsdaq-core/Macros/CoutMacros.h" 00004 #include "otsdaq-core/MessageFacility/MessageFacility.h" 00005 #include "otsdaq-core/XmlUtilities/ConvertFromXML.h" 00006 #include "otsdaq-core/XmlUtilities/ConvertToXML.h" 00007 00008 #include <stdexcept> 00009 #include <xercesc/dom/DOM.hpp> 00010 #include <xercesc/dom/DOMDocument.hpp> 00011 #include <xercesc/dom/DOMDocumentType.hpp> 00012 #include <xercesc/dom/DOMElement.hpp> 00013 #include <xercesc/dom/DOMImplementation.hpp> 00014 #include <xercesc/dom/DOMImplementationLS.hpp> 00015 #include <xercesc/dom/DOMImplementationRegistry.hpp> 00016 #include <xercesc/parsers/XercesDOMParser.hpp> 00017 //#include <xercesc/dom/DOMLSSerializer.hpp> 00018 //#include <xercesc/dom/DOMLSOutput.hpp> 00019 #include <xercesc/dom/DOMNodeIterator.hpp> 00020 #include <xercesc/dom/DOMNodeList.hpp> 00021 #include <xercesc/dom/DOMText.hpp> 00022 #include <xercesc/validators/common/Grammar.hpp> 00023 00024 #include <xercesc/parsers/XercesDOMParser.hpp> 00025 #include <xercesc/util/XMLUni.hpp> 00026 #include <xercesc/util/XercesDefs.hpp> 00027 00028 #include <xercesc/framework/LocalFileFormatTarget.hpp> 00029 #include <xercesc/util/OutOfMemoryException.hpp> 00030 00031 #include <iostream> 00032 #include <list> 00033 #include <sstream> 00034 00035 #include <errno.h> 00036 #include <sys/stat.h> 00037 #include <sys/types.h> 00038 #include <unistd.h> 00039 00040 using namespace ots; 00041 00042 //============================================================================== 00043 XmlDocument::XmlDocument(std::string rootName) : rootTagName_(rootName) 00044 { 00045 // INIT_MF("XmlDocument"); 00046 //__COUT__ << "in" << std::endl; 00047 initDocument(); 00048 rootElement_ = theDocument_->getDocumentElement(); 00049 //__COUT__ << "out" << std::endl; 00050 } 00051 00052 //============================================================================== 00053 XmlDocument::XmlDocument(const XmlDocument& doc) : rootTagName_(doc.rootTagName_) 00054 { 00055 //__COUT__ << "in" << std::endl; 00056 *this = doc; 00057 //__COUT__ << "out" << std::endl; 00058 } 00059 00060 //============================================================================== 00061 XmlDocument& XmlDocument::operator=(const XmlDocument& doc) 00062 { 00063 //__COUT__ << "in" << std::endl; 00064 initDocument(); 00065 rootElement_ = theDocument_->getDocumentElement(); 00066 recursiveElementCopy(doc.rootElement_, rootElement_); 00067 //__COUT__ << "out" << std::endl; 00068 return *this; 00069 } 00070 00071 //============================================================================== 00072 XmlDocument::~XmlDocument(void) 00073 { 00074 //__COUT__ << "Xml Destructor" << std::endl; 00075 terminatePlatform(); 00076 } 00077 00078 //============================================================================== 00079 void XmlDocument::initDocument(void) 00080 { 00081 initPlatform(); 00082 00083 theImplementation_ = 00084 xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML("Core")); 00085 00086 if(theImplementation_) 00087 { 00088 try 00089 { 00090 theDocument_ = theImplementation_->createDocument( 00091 CONVERT_TO_XML("http://www.w3.org/2001/XMLSchema-instance"), // root 00092 // element 00093 // namespace 00094 // URI. 00095 CONVERT_TO_XML(rootTagName_), // root element name 00096 0); // theDocument_ type object (DTD). 00097 } 00098 catch(const xercesc::OutOfMemoryException&) 00099 { 00100 XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" 00101 << XERCES_STD_QUALIFIER endl; 00102 } 00103 catch(const xercesc::DOMException& e) 00104 { 00105 XERCES_STD_QUALIFIER cerr << "DOMException code is: " << e.code 00106 << XERCES_STD_QUALIFIER endl; 00107 } 00108 catch(const xercesc::XMLException& e) 00109 { 00110 __COUT__ << "Error Message: " << XML_TO_CHAR(e.getMessage()) << std::endl; 00111 } 00112 catch(...) 00113 { 00114 XERCES_STD_QUALIFIER cerr << "An error occurred creating the theDocument_" 00115 << XERCES_STD_QUALIFIER endl; 00116 } 00117 } 00118 else 00119 XERCES_STD_QUALIFIER cerr << "Requested theImplementation_ is not supported" 00120 << XERCES_STD_QUALIFIER endl; 00121 } 00122 00123 //============================================================================== 00124 void XmlDocument::initPlatform(void) 00125 { 00126 try 00127 { 00128 xercesc::XMLPlatformUtils::Initialize(); // Initialize Xerces infrastructure 00129 //__COUT__ << "Initialized new 00130 // theDocument_" << std::endl; 00131 } 00132 catch(xercesc::XMLException& e) 00133 { 00134 __COUT__ << "XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage()) 00135 << std::endl; 00136 } 00137 } 00138 00139 //============================================================================== 00140 void XmlDocument::terminatePlatform(void) 00141 { 00142 try 00143 { 00144 //__COUT__ << "Releasing the document" << std::endl; 00145 theDocument_->release(); 00146 //__COUT__ << "document released" << std::endl; 00147 } 00148 catch(...) 00149 { 00150 XERCES_STD_QUALIFIER cerr << "An error occurred destroying the theDocument_" 00151 << XERCES_STD_QUALIFIER endl; 00152 } 00153 00154 try 00155 { 00156 xercesc::XMLPlatformUtils::Terminate(); // Terminate after release of memory 00157 } 00158 catch(xercesc::XMLException& e) 00159 { 00160 __COUT__ << "XML toolkit teardown error: " << XML_TO_CHAR(e.getMessage()) 00161 << std::endl; 00162 // XMLString::release(&message); 00163 } 00164 } 00165 00166 //============================================================================== 00167 // addTextElementToParent 00168 // add to parent by pointer to parent 00169 // returns pointer to element that is added 00170 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName, 00171 std::string childText, 00172 xercesc::DOMElement* parent) 00173 { 00174 if(parent == 0) 00175 { 00176 __SS__ << "Illegal Null Parent Pointer!" << __E__; 00177 __SS_THROW__; 00178 // return 0; 00179 } 00180 xercesc::DOMElement* child; 00181 try 00182 { 00183 child = theDocument_->createElement(CONVERT_TO_XML(childName)); 00184 } 00185 catch(xercesc::DOMException& e) 00186 { 00187 __COUT__ << "Can't use the name: " << childName 00188 << " to create the child element because the exception says: " 00189 << XML_TO_CHAR(e.getMessage()) 00190 << ". Very likely you have a name that starts with a number and that's " 00191 "not allowed!" 00192 << std::endl; 00193 } 00194 parent->appendChild(child); 00195 00196 try 00197 { 00198 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(childText))); 00199 } 00200 catch(...) // sometimes see TranscodingException 00201 { 00202 __COUT_ERR__ << "Error caught attempting to create a text node for this text: " 00203 << childText << ". Converting instead to 'Illegal text..'" 00204 << std::endl; 00205 child->appendChild(theDocument_->createTextNode( 00206 CONVERT_TO_XML("Illegal text content blocked."))); 00207 } 00208 00209 return child; 00210 } 00211 00212 //============================================================================== 00213 // addTextElementToParent 00214 // add to parent by instance number of parent name 00215 // returns pointer to element that is added 00216 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName, 00217 std::string childText, 00218 std::string parentName, 00219 unsigned int parentIndex) 00220 { 00221 xercesc::DOMNodeList* nodeList = 00222 theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName)); 00223 00224 if(parentIndex >= nodeList->getLength()) 00225 { 00226 __COUT__ << "WARNING: Illegal parent index attempted in tags with name: " 00227 << parentName << ", index: " << parentIndex << std::endl; 00228 return 0; // illegal index attempted 00229 } 00230 00231 return addTextElementToParent( 00232 childName, childText, (xercesc::DOMElement*)(nodeList->item(parentIndex))); 00233 } 00234 00235 //============================================================================== 00236 void XmlDocument::copyDocument(const xercesc::DOMDocument* toCopy, 00237 xercesc::DOMDocument* copy) 00238 { 00239 recursiveElementCopy(toCopy->getDocumentElement(), copy->getDocumentElement()); 00240 } 00241 00242 //============================================================================== 00243 void XmlDocument::recursiveElementCopy(const xercesc::DOMElement* toCopy, 00244 xercesc::DOMElement* copy) 00245 { 00246 xercesc::DOMNodeList* nodeListToCopy = 00247 toCopy->getChildNodes(); // get all children of the list to copy 00248 xercesc::DOMNode* iNode; 00249 xercesc::DOMDocument* copyDocument = copy->getOwnerDocument(); 00250 for(unsigned int i = 0; i < nodeListToCopy->getLength(); i++) 00251 { 00252 iNode = nodeListToCopy->item(i); 00253 xercesc::DOMElement* child = copyDocument->createElement(iNode->getNodeName()); 00254 copy->appendChild(child); 00255 if(iNode->getFirstChild() != 0 && 00256 iNode->getFirstChild()->getNodeType() == 00257 xercesc::DOMNode::TEXT_NODE) // if has a text node first, insert as value 00258 // attribute 00259 { 00260 child->appendChild( 00261 copyDocument->createTextNode(child->getFirstChild()->getNodeValue())); 00262 } 00263 recursiveElementCopy((xercesc::DOMElement*)(iNode), child); 00264 } 00265 } 00266 00267 //============================================================================== 00268 // XmlDocument::addElementToParent 00269 // Add field/value element to XML doc at parent 00270 // On Success, The child index of the added element with respect to the parent is 00271 // returned and can be used to add 00272 // children to the new element 00273 // On Failure, return -1 00274 /* 00275 unsigned int XmlDocument::addElementToParent(std::string field, std::string value, 00276 xercesc::DOMElement *parentEl, bool verbose) 00277 { 00278 DOMNodeList *nodeList = parentEl->getChildNodes(); //get all children 00279 00280 if(verbose) 00281 { 00282 //display parent info 00283 //__COUT__ << "Parent Name: " << XML_TO_CHAR(parentEl->getNodeName()) << " Field: 00284 " << field << " Value: " << value << std::endl; if( parentEl->getFirstChild() != NULL && 00285 parentEl->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) 00286 __COUT__ << "Parent's First Child Node Value: " << 00287 XML_TO_CHAR(parentEl->getFirstChild()->getNodeValue()) << std::endl; 00288 } 00289 00290 //add field/value element 00291 DOMElement *newEl = theDocument_->createElement(CONVERT_TO_XML(field)); 00292 parentEl->appendChild(newEl); 00293 00294 DOMText* valueStr = theDocument_->createTextNode(CONVERT_TO_XML(value)); 00295 newEl->appendChild(valueStr); 00296 00297 if( parentEl->getFirstChild() != NULL && parentEl->getFirstChild()->getNodeType() == 00298 DOMNode::TEXT_NODE) return nodeList->getLength() - 2; //return child index among parent's 00299 children, not counting first child text node return nodeList->getLength() - 1; //return 00300 child index among parent's children 00301 } 00302 */ 00303 //============================================================================== 00304 // XmlDocument::addDataElement 00305 // Add field/value element to XML doc at parent which is returned from 00306 // getElementsByTagName(parentName), entry number parentNameIndex 00307 // On Success, The child index of the added element with respect to the parent is 00308 // returned and can be used to add 00309 // children to the new element 00310 // On Failure, return -1 00311 /* 00312 unsigned int XmlDocument::addDataElement ( std::string field, std::string value, 00313 std::string parentName, unsigned int parentNameIndex) 00314 { 00315 DOMNodeList *nodeList = 00316 theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName)); 00317 00318 if(parentNameIndex >= nodeList->getLength()) { 00319 __COUT__ << "illegal parent index attempted in tags with name: " << parentName << 00320 ", index: " << parentNameIndex << std::endl; return -1; //illegal index attempted 00321 } 00322 00323 return addElementToParent(field,value,(DOMElement*)(nodeList->item(parentNameIndex))); 00324 } 00325 */ 00326 //============================================================================== 00327 // XmlDocument::addDataElement 00328 // Add field/value element to XML doc at parentIndexArray (with depth of parent indicated 00329 // by parentIndexArraySize) If parentIndexArray = NULL, element is added with <DATA> 00330 // parent otherwise, parentIndexArray indicates the parent within the node list for 00331 //<DATA> where the element will be added 00332 // On Success, The child index of the added element with respect to the parent is 00333 // returned and can be used to add 00334 // children to the new element 00335 // On Failure, return -1 00336 /* 00337 unsigned int XmlDocument::addDataElement ( std::string field, std::string value, unsigned 00338 int *parentIndexArray, unsigned int parentIndexArraySize) 00339 { 00340 00341 //__COUT__ << "field: " << field << ", value: " << value << ", parent: " << 00342 parentIndexArraySize << std::endl; 00343 00344 DOMElement *parentEl = dataElement; // initialize parent to <DATA> 00345 00346 if(parentIndexArray) //if there passed an array find parent relative to data element 00347 { 00348 //__COUT__ << "Using Parent Index Array" << std::endl; 00349 00350 DOMNodeList *nodeList; 00351 00352 //iterate through nested parents based on parentIndexArray 00353 unsigned int tmpi,cntNotTxt; 00354 for(unsigned int i=0;i<parentIndexArraySize;++i) 00355 { 00356 nodeList = parentEl->getChildNodes(); //get all children 00357 cntNotTxt = 0; 00358 00359 //get cntNotTxt to proper non text node 00360 for(tmpi=0;tmpi<nodeList->getLength();++tmpi) 00361 { 00362 if(((DOMElement*)(nodeList->item(tmpi)))->getNodeType() == 00363 DOMNode::TEXT_NODE) continue; //skip text nodes 00364 00365 if(cntNotTxt == parentIndexArray[i]) break; //at proper parent node! 00366 ++cntNotTxt; //else look for next 00367 } 00368 00369 //in theory, only first child can be text - ignore text node children 00370 //if(parentEl->getFirstChild() != NULL && 00371 parentEl->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) ++tmpi; 00372 00373 if(tmpi >= nodeList->getLength()) { 00374 __COUT__ << "illegal child index attempted in nested parents: " << 00375 parentIndexArray[i] << ", depth: " << i << ", tmpi: " << tmpi << std::endl; return -1; 00376 //illegal child index attempted in nested parents 00377 } 00378 00379 parentEl = (DOMElement*)(nodeList->item(tmpi)); 00380 } 00381 } 00382 00383 return addElementToParent(field,value,parentEl); 00384 } 00385 */ 00386 //============================================================================== 00387 // XmlDocument::addXmlData 00388 // Append <DATA> from xmldoc to this XML doc 00389 // On Success, The child index within <DATA> of the first element is returned 00390 // On Failure, return -1 00391 /* 00392 unsigned int XmlDocument::addXmlData (XmlDocument *xmldoc) 00393 { 00394 // 00395 00396 int retIndex = dataElement->getChildNodes()->getLength(); //will be index of first 00397 appended data element 00398 00399 //add all first level child elements of data and recurse on them 00400 DOMNodeList *nodeList = xmldoc->dataElement->getChildNodes(); //get all children 00401 within data for(unsigned int i = 0; i<nodeList->getLength();++i) 00402 { 00403 if(nodeList->item(i)->getNodeType() == DOMNode::TEXT_NODE) //ignore text node 00404 children continue; 00405 00406 recursiveAddElementToParent((DOMElement*)(nodeList->item(i)),dataElement); 00407 } 00408 00409 return retIndex; 00410 } 00411 */ 00412 //============================================================================== 00413 // XmlDocument::recursiveAddElementToParent 00414 // add currEl and its children tree to parentEl 00415 /* 00416 void XmlDocument::recursiveAddElementToParent (DOMElement *currEl, DOMElement *parentEl) 00417 { 00418 std::string field, value = ""; 00419 00420 //char *tmpField = 00421 field = XML_TO_CHAR(currEl->getNodeName());//XML_TO_CHAR(currEl->getNodeName()); 00422 //field = tmpField; 00423 //XMLString::release( &tmpField ); 00424 00425 if( currEl->getFirstChild() != NULL && currEl->getFirstChild()->getNodeType() == 00426 DOMNode::TEXT_NODE) //if has a text node first, insert as value attribute value = 00427 escapeString(XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())); 00428 00429 //insert currEl 00430 addElementToParent(field,value,parentEl); 00431 00432 //insert rest of currEl tree 00433 DOMNodeList *nodeList = currEl->getChildNodes(); //get all children of currEl 00434 for(unsigned int i = 0; i<nodeList->getLength();++i) 00435 { 00436 if(nodeList->item(i)->getNodeType() == DOMNode::TEXT_NODE) //ignore text node 00437 children continue; 00438 00439 recursiveAddElementToParent((DOMElement*)(nodeList->item(i)),currEl); 00440 } 00441 } 00442 */ 00443 //============================================================================== 00444 // XmlDocument::outputXmlDocument 00445 // recurse through XML theDocument_ and std out and output to stream parameter if not 00446 // null 00447 void XmlDocument::outputXmlDocument(std::ostringstream* out, bool dispStdOut) 00448 { 00449 recursiveOutputXmlDocument(theDocument_->getDocumentElement(), out, dispStdOut); 00450 } 00451 00452 //============================================================================== 00453 // XmlDocument::recursiveOutputXmlDocument 00454 // recursively printout XML theDocument_ to std out and output stream if not null 00455 void XmlDocument::recursiveOutputXmlDocument(xercesc::DOMElement* currEl, 00456 std::ostringstream* out, 00457 bool dispStdOut, 00458 std::string tabStr) 00459 { 00460 // open field tag 00461 if(dispStdOut) 00462 __COUT__ << tabStr << "<" << XML_TO_CHAR(currEl->getNodeName()); 00463 if(out) 00464 *out << tabStr << "<" << XML_TO_CHAR(currEl->getNodeName()); 00465 00466 // insert value if text node child 00467 if(currEl->getFirstChild() != NULL && 00468 currEl->getFirstChild()->getNodeType() == 00469 xercesc::DOMNode::TEXT_NODE) // if has a text node first, insert as value 00470 // attribute 00471 { 00472 if(dispStdOut) 00473 std::cout << " value='" 00474 << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) << "'"; 00475 if(out) 00476 *out << " value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) 00477 << "'"; 00478 } 00479 00480 xercesc::DOMNodeList* nodeList = currEl->getChildNodes(); // get all children 00481 00482 // close opening field tag 00483 if(dispStdOut) 00484 std::cout << ((nodeList->getLength() == 0 || 00485 (nodeList->getLength() == 1 && 00486 currEl->getFirstChild()->getNodeType() == 00487 xercesc::DOMNode::TEXT_NODE)) 00488 ? "/" 00489 : "") 00490 << ">" 00491 << " len:" << nodeList->getLength() << std::endl; 00492 if(out) 00493 *out << ((nodeList->getLength() == 0 || 00494 (nodeList->getLength() == 1 && 00495 currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)) 00496 ? "/" 00497 : "") 00498 << ">" << std::endl; 00499 00500 // insert children 00501 std::string newTabStr = tabStr + "\t"; 00502 for(unsigned int i = 0; i < nodeList->getLength(); ++i) 00503 if(nodeList->item(i)->getNodeType() != 00504 xercesc::DOMNode::TEXT_NODE) // ignore text node children 00505 recursiveOutputXmlDocument( 00506 (xercesc::DOMElement*)(nodeList->item(i)), out, dispStdOut, newTabStr); 00507 00508 // close tag if children 00509 if(nodeList->getLength() > 1 || 00510 (nodeList->getLength() == 1 && 00511 currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE)) 00512 { 00513 if(dispStdOut) 00514 __COUT__ << tabStr << "</" << XML_TO_CHAR(currEl->getNodeName()) << ">" 00515 << std::endl; 00516 if(out) 00517 *out << tabStr << "</" << XML_TO_CHAR(currEl->getNodeName()) << ">" 00518 << std::endl; 00519 } 00520 } 00521 00522 //============================================================================== 00523 // XmlDocument::getDataElement 00524 // returns the value for field found occurance number of times 00525 // returns empty std::string "" if field was not found 00526 /* 00527 std::string XmlDocument::getDataElement (const std::string field, const unsigned int 00528 occurance) 00529 { 00530 unsigned int count = 0; 00531 return recursiveFindElement(theDocument_->getDocumentElement(),field,occurance,count); 00532 } 00533 */ 00534 //============================================================================== 00535 // XmlDocument::recursiveFindElement 00536 // recursively searches and returns the value for field found occurance number of times 00537 /* 00538 std::string XmlDocument::recursiveFindElement (DOMElement *currEl, const std::string 00539 field, const unsigned int occurance, unsigned int &count) 00540 { 00541 if (XML_TO_CHAR(currEl->getNodeName()) == field && occurance == count++) //found, 00542 done!! 00543 { 00544 if( currEl->getFirstChild() != NULL && currEl->getFirstChild()->getNodeType() == 00545 DOMNode::TEXT_NODE) //if has a text node first, return as value attribute return 00546 escapeString(XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())); else return ""; 00547 //empty value attribute 00548 } 00549 00550 std::string retStr; 00551 //look through children recursively 00552 DOMNodeList *nodeList = currEl->getChildNodes(); //get all children 00553 for(unsigned int i = 0; i<nodeList->getLength();++i) 00554 if(nodeList->item(i)->getNodeType() != DOMNode::TEXT_NODE) //ignore text node 00555 children 00556 { 00557 retStr = recursiveFindElement 00558 ((DOMElement*)(nodeList->item(i)),field,occurance,count); if(retStr != "") return retStr; 00559 //found among children already, done 00560 //else continue search within children recursively 00561 } 00562 return ""; //nothing found 00563 } 00564 */ 00565 //============================================================================== 00566 // XmlDocument::getAllDataElements 00567 // returns all of the values found for the field in a vector 00568 // if none found vector will have size 0 00569 /* 00570 std::vector<std::string> XmlDocument::getAllDataElements (std::string field) 00571 { 00572 vector<string> retVec; 00573 00574 recursiveFindAllElements(theDocument_->getDocumentElement(),field,&retVec); 00575 00576 return retVec; 00577 } 00578 */ 00579 //============================================================================== 00580 // XmlDocument::recursiveFindElement 00581 // recursively searches and returns the value for field found occurance number of times 00582 /* 00583 void XmlDocument::recursiveFindAllElements (DOMElement *currEl, const std::string 00584 field,std::vector<std::string> *retVec) 00585 { 00586 if (XML_TO_CHAR(currEl->getNodeName()) == field && 00587 currEl->getFirstChild() != NULL && currEl->getFirstChild()->getNodeType() == 00588 DOMNode::TEXT_NODE) //if has a text node first, return as value attribute 00589 retVec->push_back(XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())); 00590 00591 00592 //look through children recursively 00593 DOMNodeList *nodeList = currEl->getChildNodes(); //get all children 00594 for(unsigned int i = 0; i<nodeList->getLength();++i) 00595 if(nodeList->item(i)->getNodeType() != DOMNode::TEXT_NODE) //ignore text node 00596 children recursiveFindAllElements ((DOMElement*)(nodeList->item(i)),field,retVec); 00597 } 00598 */ 00599 //============================================================================== 00600 // XmlDocument::escapeString 00601 // convert quotes to html quote characters ' = ' and " = " 00602 // remove new line characters 00603 // and (if !allowWhiteSpace) remove white space (so that read from file white space 00604 // artifact removed) 00605 // 00606 // convert & = & 00607 // if(allowWhiteSpace) convert \t to 8   spaces and \n to <br> 00608 std::string XmlDocument::escapeString(std::string inString, bool allowWhiteSpace) 00609 { 00610 bool doit = false; 00611 00612 unsigned int ws = -1; 00613 char htmlTmp[6]; 00614 00615 for(unsigned int i = 0; i < inString.length(); i++) 00616 if(inString[i] != ' ') 00617 { 00618 if(doit) 00619 __COUT__ << inString[i] << ":" << (int)inString[i] << ":" << inString 00620 << std::endl; 00621 00622 // remove new lines and unprintable characters 00623 if(inString[i] == '\r' || inString[i] == '\n' || // remove new line chars 00624 inString[i] == '\t' || // remove tabs 00625 inString[i] < 32 || // remove un-printable characters (they mess up xml 00626 // interpretation) 00627 (inString[i] > char(126) && 00628 inString[i] < char(161))) // this is aggravated by the bug in 00629 // MFextensions (though Eric says he fixed on 00630 // 8/24/2016) Note: greater than 255 should be 00631 // impossible if by byte (but there are html 00632 // chracters in 300s and 8000s) 00633 { 00634 if( // maintain new lines and tabs 00635 inString[i] == '\n') 00636 { 00637 if(allowWhiteSpace) 00638 { 00639 sprintf(htmlTmp, "&#%3.3d", inString[i]); 00640 inString.insert(i, htmlTmp); // insert html str sequence 00641 inString.replace( 00642 i + 5, 1, 1, ';'); // replace special character with ; 00643 i += 6; // skip to next char to check 00644 --i; 00645 } 00646 else // translate to ' ' 00647 inString[i] = ' '; 00648 } 00649 else if( // maintain new lines and tabs 00650 inString[i] == '\t') 00651 { 00652 if(allowWhiteSpace) 00653 { 00654 if(0) 00655 { 00656 // tab = 8 spaces 00657 sprintf(htmlTmp, 00658 "        "); 00659 inString.insert(i, htmlTmp); // insert html str sequence 00660 inString.replace( 00661 i + 47, 1, 1, ';'); // replace special character with ; 00662 i += 48; // skip to next char to check 00663 --i; 00664 } 00665 else // tab = 0x09 00666 { 00667 sprintf(htmlTmp, "	"); 00668 inString.insert(i, htmlTmp); // insert html str sequence 00669 inString.replace( 00670 i + 5, 1, 1, ';'); // replace special character with ; 00671 i += 6; // skip to next char to check 00672 --i; 00673 } 00674 } 00675 else // translate to ' ' 00676 inString[i] = ' '; 00677 } 00678 else 00679 { 00680 inString.erase(i, 1); // erase character 00681 --i; // step back so next char to check is correct 00682 } 00683 if(doit) 00684 __COUT__ << inString << std::endl; 00685 continue; 00686 } 00687 00688 if(doit) 00689 __COUT__ << inString << std::endl; 00690 00691 // replace special characters 00692 if(inString[i] == '\"' || inString[i] == '\'') 00693 { 00694 inString.insert(i, 00695 (inString[i] == '\'') 00696 ? "&apos" 00697 : """); // insert HTML name before quotes 00698 inString.replace(i + 5, 1, 1, ';'); // replace special character with ; 00699 i += 5; // skip to next char to check 00700 //__COUT__ << inString << std::endl; 00701 } 00702 else if(inString[i] == '&') 00703 { 00704 inString.insert(i, "&"); // insert HTML name before special character 00705 inString.replace(i + 4, 1, 1, ';'); // replace special character with ; 00706 i += 4; // skip to next char to check 00707 } 00708 else if(inString[i] == '<' || inString[i] == '>') 00709 { 00710 inString.insert( 00711 i, 00712 (inString[i] == '<') 00713 ? "<" 00714 : ">"); // insert HTML name before special character 00715 inString.replace(i + 3, 1, 1, ';'); // replace special character with ; 00716 i += 3; // skip to next char to check 00717 } 00718 else if(inString[i] >= char(161) && 00719 inString[i] <= char(255)) // printable special characters 00720 { 00721 sprintf(htmlTmp, "&#%3.3d", inString[i]); 00722 inString.insert(i, htmlTmp); // insert html number sequence 00723 inString.replace(i + 5, 1, 1, ';'); // replace special character with ; 00724 i += 5; // skip to next char to check 00725 } 00726 00727 if(doit) 00728 __COUT__ << inString << std::endl; 00729 00730 ws = i; // last non white space char 00731 } 00732 else if(allowWhiteSpace) // keep white space if allowed 00733 { 00734 if(i - 1 == ws) 00735 continue; // dont do anything for first white space 00736 00737 // for second white space add 2, and 1 from then 00738 if(0 && i - 2 == ws) 00739 { 00740 inString.insert(i, " "); // insert html space 00741 i += 6; // skip to point at space again 00742 } 00743 inString.insert(i, " "); // insert html space 00744 inString.replace(i + 5, 1, 1, ';'); // replace special character with ; 00745 i += 5; // skip to next char to check 00746 // ws = i; 00747 } 00748 00749 if(doit) 00750 __COUT__ << inString.size() << " " << ws << std::endl; 00751 00752 // inString.substr(0,ws+1); 00753 00754 if(doit) 00755 __COUT__ << inString.size() << " " << inString << std::endl; 00756 00757 if(allowWhiteSpace) // keep all white space 00758 return inString; 00759 // else trim trailing white space 00760 00761 if(ws == (unsigned int)-1) 00762 return ""; // empty std::string since all white space 00763 return inString.substr(0, ws + 1); // trim right white space 00764 } 00765 00766 //============================================================================== 00767 // XmlDocument::recursiveRemoveChild 00768 // remove child and all of child's sub-tree from parent 00769 void XmlDocument::recursiveRemoveChild(xercesc::DOMElement* childEl, 00770 xercesc::DOMElement* parentEl) 00771 { 00772 // release child's children first 00773 xercesc::DOMNodeList* nodeList = 00774 childEl->getChildNodes(); // get all children within data 00775 for(unsigned int i = 0; i < nodeList->getLength(); ++i) 00776 recursiveRemoveChild( 00777 (xercesc::DOMElement*)(nodeList->item(nodeList->getLength() - 1 - i)), 00778 childEl); 00779 00780 // then release child 00781 parentEl->removeChild(childEl); 00782 childEl->release(); 00783 } 00784 00785 //============================================================================== 00786 // XmlDocument::saveXmlDocument 00787 // wrapper for private outputXML 00788 // Warning: filePath must be accessible or program will crash! 00789 void XmlDocument::saveXmlDocument(std::string filePath) 00790 { 00791 __COUT__ << "Saving theDocument_ to file: " << filePath << std::endl; 00792 // Return the first registered theImplementation_ that has the desired features. In 00793 // this case, we are after a DOM theImplementation_ that has the LS feature... or 00794 // Load/Save. DOMImplementation *theImplementation_ = 00795 // DOMImplementationRegistry::getDOMImplementation(L"LS"); 00796 xercesc::DOMImplementation* saveImplementation = 00797 xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML("LS")); 00798 00799 //__COUT__ << "XERCES Version: " << _XERCES_VERSION << std::endl; 00800 00801 #if _XERCES_VERSION >= 30000 00802 00803 //__COUT__ << "making file" << filePath << std::endl; 00804 // Create a DOMLSSerializer which is used to serialize a DOM tree into an XML 00805 // theDocument_. 00806 xercesc::DOMLSSerializer* serializer = 00807 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSSerializer(); 00808 00809 // Make the output more human readable by inserting line feeds. 00810 if(serializer->getDomConfig()->canSetParameter( 00811 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true)) 00812 serializer->getDomConfig()->setParameter( 00813 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true); 00814 00815 // The end-of-line sequence of characters to be used in the XML being written out. 00816 serializer->setNewLine(CONVERT_TO_XML("\r\n")); 00817 00818 // Convert the path into Xerces compatible XMLCh*. 00819 // XMLCh *tempFilePath = const_cast<XMLCh*>(CONVERT_TO_XML(filePath)); 00820 00821 // Specify the target for the XML output. 00822 xercesc::XMLFormatTarget* formatTarget; 00823 try 00824 { 00825 // formatTarget = new xercesc::LocalFileFormatTarget(tempFilePath); 00826 formatTarget = new xercesc::LocalFileFormatTarget(filePath.c_str()); 00827 } 00828 catch(...) 00829 { 00830 __COUT__ << "Inaccessible file path: " << filePath << std::endl; 00831 serializer->release(); 00832 // xercesc::XMLString::release(&tempFilePath); 00833 00834 return; 00835 } 00836 00837 // Create a new empty output destination object. 00838 xercesc::DOMLSOutput* output = 00839 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSOutput(); 00840 00841 // Set the stream to our target. 00842 output->setByteStream(formatTarget); 00843 // Write the serialized output to the destination. 00844 serializer->write(theDocument_, output); 00845 serializer->release(); 00846 // xercesc::XMLString::release(&tempFilePath); 00847 delete formatTarget; 00848 #else 00849 00850 xercesc::DOMWriter* serializer = 00851 ((xercesc::DOMImplementationLS*)saveImplementation)->createDOMWriter(); 00852 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true); 00853 00854 /* 00855 Choose a location for the serialized output. The 3 options are: 00856 1) StdOutFormatTarget (std output stream - good for debugging) 00857 2) MemBufFormatTarget (to Memory) 00858 3) LocalFileFormatTarget (save to file) 00859 (Note: You'll need a different header file for each one) 00860 */ 00861 // XMLFormatTarget* pTarget = new StdOutFormatTarget(); 00862 // Convert the path into Xerces compatible XMLCh*. 00863 XMLCh* tempFilePath = xercesc::XMLString::transcode(filePath.c_str()); 00864 xercesc::XMLFormatTarget* formatTarget; 00865 try 00866 { 00867 formatTarget = new xercesc::LocalFileFormatTarget(tempFilePath); 00868 } 00869 catch(...) 00870 { 00871 __COUT__ << "Inaccessible file path: " << filePath << std::endl; 00872 serializer->release(); 00873 xercesc::XMLString::release(&tempFilePath); 00874 return; 00875 } 00876 00877 // Write the serialized output to the target. 00878 00879 serializer->writeNode(formatTarget, *theDocument_); 00880 serializer->release(); 00881 xercesc::XMLString::release(&tempFilePath); 00882 delete formatTarget; 00883 #endif 00884 00885 // Cleanup. 00886 //__COUT__ << "delete format target" << std::endl; 00887 00888 #if _XERCES_VERSION >= 30000 00889 00890 //__COUT__ << "delete output0" << std::endl; 00891 output->release(); 00892 //__COUT__ << "delete output1" << std::endl; 00893 00894 #endif 00895 } 00896 00897 //============================================================================== 00898 bool XmlDocument::loadXmlDocument(std::string filePath) 00899 { 00900 __COUT__ << "Loading theDocument_ from file: " << filePath << std::endl; 00901 00902 struct stat fileStatus; 00903 00904 if(stat(filePath.c_str(), &fileStatus) != 0) 00905 { 00906 __COUT__ << "File not accessible." << std::endl; 00907 return false; 00908 } 00909 00910 // reset xml platform and theDocument_ 00911 terminatePlatform(); 00912 initPlatform(); 00913 00914 xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser; 00915 // Configure xercesc::DOM parser. 00916 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto); 00917 parser->setDoNamespaces(true); 00918 parser->setDoSchema(true); 00919 parser->useCachedGrammarInParse(false); 00920 00921 try 00922 { 00923 parser->parse(filePath.c_str()); 00924 00925 // theDocument_ memory object owned by the parent parser object 00926 theDocument_ = parser->adoptDocument(); // instead of getDocument() so parser 00927 // will not free theDocument_ when 00928 // released 00929 00930 // Get the top-level element: Name is "root". No attributes for "root" 00931 rootElement_ = theDocument_->getDocumentElement(); 00932 if(!rootElement_) 00933 throw(std::runtime_error("empty XML theDocument_")); 00934 } 00935 catch(xercesc::XMLException& e) 00936 { 00937 __COUT__ << "Error parsing file." << std::endl; 00938 return false; 00939 } 00940 delete parser; 00941 00942 return true; 00943 } 00944 00945 //============================================================================== 00946 // XmlDocument::recursiveOutputXmlDocument 00947 // recursively printout XML theDocument_ to std out and output stream if not null 00948 /* 00949 void XmlDocument::recursiveFixTextFields(DOMElement *currEl) 00950 { 00951 DOMNodeList *nodeList = currEl->getChildNodes(); //get all children 00952 00953 //recurse through children 00954 for(unsigned int i = 0; i<nodeList->getLength();++i) 00955 if(nodeList->item(i)->getNodeType() == DOMNode::TEXT_NODE) //fix text nodes 00956 ((DOMElement*)(nodeList->item(i)))->setTextContent(CONVERT_TO_XML( 00957 //change text value to escaped version 00958 escapeString(XML_TO_CHAR(((DOMElement*)(nodeList->item(i)))->getNodeValue())))); 00959 else 00960 recursiveFixTextFields ((DOMElement*)(nodeList->item(i))); 00961 } 00962 */