1 #include "otsdaq/XmlUtilities/HttpXmlDocument.h"
2 #include "otsdaq/Macros/CoutMacros.h"
3 #include "otsdaq/Macros/StringMacros.h"
4 #include "otsdaq/MessageFacility/MessageFacility.h"
5 #include "otsdaq/XmlUtilities/ConvertFromXML.h"
6 #include "otsdaq/XmlUtilities/ConvertToXML.h"
10 #include <xercesc/dom/DOM.hpp>
11 #include <xercesc/dom/DOMDocument.hpp>
12 #include <xercesc/dom/DOMDocumentType.hpp>
13 #include <xercesc/dom/DOMElement.hpp>
14 #include <xercesc/dom/DOMImplementation.hpp>
15 #include <xercesc/dom/DOMImplementationLS.hpp>
16 #include <xercesc/dom/DOMImplementationRegistry.hpp>
19 #include <xercesc/dom/DOMNodeIterator.hpp>
20 #include <xercesc/dom/DOMNodeList.hpp>
21 #include <xercesc/dom/DOMText.hpp>
22 #include <xercesc/validators/common/Grammar.hpp>
24 #include <xercesc/parsers/XercesDOMParser.hpp>
25 #include <xercesc/util/XMLUni.hpp>
26 #include <xercesc/util/XercesDefs.hpp>
28 #include <xercesc/framework/LocalFileFormatTarget.hpp>
29 #include <xercesc/util/OutOfMemoryException.hpp>
37 #include <sys/types.h>
60 , headerTagName_(
"HEADER")
61 , dataTagName_(
"DATA")
62 , cookieCodeTagName_(
"CookieCode")
63 , displayNameTagName_(
"DisplayName")
67 if(cookieCode !=
"" || displayName !=
"")
69 headerElement_ = theDocument_->createElement(CONVERT_TO_XML(headerTagName_));
70 rootElement_->appendChild(headerElement_);
78 dataElement_ = theDocument_->createElement(CONVERT_TO_XML(dataTagName_));
79 rootElement_->appendChild(dataElement_);
88 , headerTagName_(doc.headerTagName_)
89 , dataTagName_(doc.dataTagName_)
90 , cookieCodeTagName_(doc.cookieCodeTagName_)
91 , displayNameTagName_(doc.displayNameTagName_)
102 recursiveElementCopy(doc.rootElement_, rootElement_);
104 if(doc.headerElement_ != 0)
105 headerElement_ = (xercesc::DOMElement*)rootElement_
106 ->getElementsByTagName(CONVERT_TO_XML(headerTagName_))
109 dataElement_ = (xercesc::DOMElement*)rootElement_
110 ->getElementsByTagName(CONVERT_TO_XML(dataTagName_))
117 HttpXmlDocument::~HttpXmlDocument(
void) {}
119 void HttpXmlDocument::setHeader(std::string cookieCode, std::string displayName)
123 std::stringstream ss;
124 ss << __COUT_HDR_FL__
125 <<
"Can NOT set header to doc with a header! Only allowed for docs without "
130 if(cookieCode !=
"" || displayName !=
"")
132 headerElement_ = theDocument_->createElement(CONVERT_TO_XML(headerTagName_));
133 rootElement_->appendChild(headerElement_);
136 if(displayName !=
"")
142 xercesc::DOMElement* HttpXmlDocument::addTextElementToData(
const std::string& childName,
143 const std::string& childValue)
150 xercesc::DOMElement* HttpXmlDocument::addBinaryStringToData(
const std::string& childName,
151 const std::string& binary)
153 std::string convertStr =
"";
155 for(
unsigned int i = 0; i < binary.length(); ++i)
158 sprintf(hexStr,
"%2.2X", ((
unsigned char)binary[i]));
160 convertStr += hexStr;
172 parent = dataElement_;
174 xercesc::DOMNodeList* nodeList =
175 parent->getChildNodes();
176 unsigned int count = 0;
178 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
180 if(nodeList->item(i)->getNodeType() !=
181 xercesc::DOMNode::TEXT_NODE)
194 xercesc::DOMNodeList* nodeList =
195 dataElement_->getChildNodes();
197 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
199 if(nodeList->item(i)->getNodeType() ==
200 xercesc::DOMNode::TEXT_NODE)
222 xercesc::DOMNodeList* nodeList =
223 document.dataElement_->getChildNodes();
224 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
226 if(nodeList->item(i)->getNodeType() ==
227 xercesc::DOMNode::TEXT_NODE)
230 recursiveAddElementToParent(
231 (xercesc::DOMElement*)(nodeList->item(i)), dataElement_,
true );
241 bool allowWhiteSpace ,
244 recursiveOutputXmlDocument(theDocument_->getDocumentElement(),
255 void HttpXmlDocument::recursiveOutputXmlDocument(xercesc::DOMElement* currEl,
256 std::ostringstream* out,
259 bool allowWhiteSpace,
263 auto start = std::chrono::high_resolution_clock::now();
268 std::cout << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
270 *out << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
273 if(currEl->getFirstChild() != NULL &&
274 currEl->getFirstChild()->getNodeType() ==
275 xercesc::DOMNode::TEXT_NODE)
279 std::string nodeName = std::string(XML_TO_CHAR(currEl->getNodeName()));
281 bool isError = nodeName.length() >= 5 &&
282 (nodeName[nodeName.length() - 5] ==
'E' ||
283 nodeName[nodeName.length() - 5] ==
'e') &&
284 (nodeName[nodeName.length() - 4] ==
'R' ||
285 nodeName[nodeName.length() - 4] ==
'r') &&
286 (nodeName[nodeName.length() - 3] ==
'R' ||
287 nodeName[nodeName.length() - 3] ==
'r') &&
288 (nodeName[nodeName.length() - 2] ==
'O' ||
289 nodeName[nodeName.length() - 2] ==
'o') &&
290 (nodeName[nodeName.length() - 1] ==
'R' ||
291 nodeName[nodeName.length() - 1] ==
'r');
294 std::cout <<
" value='"
296 XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()),
303 XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()),
308 if(printErrors && isError)
309 __COUT_ERR__ <<
"xml Error-type field '" << nodeName <<
"' encountered:\n"
310 << XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()) << __E__;
315 auto end = std::chrono::high_resolution_clock::now();
317 std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
318 __COUTT__ << tabStr << XML_TO_CHAR(currEl->getNodeName()) <<
" -- Time taken to call recurse xml out = " << duration <<
" milliseconds." << std::endl;
322 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
326 auto end = std::chrono::high_resolution_clock::now();
328 std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
329 __COUTT__ << tabStr << XML_TO_CHAR(currEl->getNodeName()) <<
" -- Time taken to call recurse xml out = " << duration <<
" milliseconds." << std::endl;
335 std::cout << ((nodeList->getLength() == 0 ||
336 (nodeList->getLength() == 1 &&
337 currEl->getFirstChild()->getNodeType() ==
338 xercesc::DOMNode::TEXT_NODE))
342 <<
" len:" << nodeList->getLength() << std::endl;
347 !(std::string(XML_TO_CHAR(currEl->getNodeName())) ==
"ROOT" ||
348 std::string(XML_TO_CHAR(currEl->getNodeName())) ==
"HEADER" ||
349 std::string(XML_TO_CHAR(currEl->getNodeName())) ==
"DATA" ||
350 std::string(XML_TO_CHAR(currEl->getNodeName())) ==
"node" ||
351 std::string(XML_TO_CHAR(currEl->getNodeName())) ==
"nodes"))
355 XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()),
357 <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">" << std::endl;
361 *out << ((nodeList->getLength() == 0 ||
362 (nodeList->getLength() == 1 &&
363 currEl->getFirstChild()->getNodeType() ==
364 xercesc::DOMNode::TEXT_NODE))
369 if(printErrors && strcmp(XML_TO_CHAR(currEl->getNodeName()),
"Error") == 0)
370 __COUT_ERR__ <<
"xml field 'Error' encountered:\n"
371 << XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())
378 auto end = std::chrono::high_resolution_clock::now();
380 std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
381 __COUTT__ << tabStr << XML_TO_CHAR(currEl->getNodeName()) <<
" " << nodeList->getLength() <<
382 " -- Time taken to call recurse xml out = " << duration <<
" milliseconds." << std::endl;
387 std::string newTabStr = tabStr +
"\t";
388 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
389 if(nodeList->item(i)->getNodeType() !=
390 xercesc::DOMNode::TEXT_NODE)
391 recursiveOutputXmlDocument(
392 (xercesc::DOMElement*)(nodeList->item(i)),
400 auto end = std::chrono::high_resolution_clock::now();
402 std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
403 __COUTT__ << tabStr << XML_TO_CHAR(currEl->getNodeName()) <<
" -- Time taken to call recurse xml out = " << duration <<
" milliseconds." << std::endl;
407 if(currEl == dataElement_ &&
408 dataSs_.str().length())
411 std::cout << dataSs_.str() << std::endl;
413 *out << dataSs_.str() << std::endl;
417 if(nodeList->getLength() > 1 ||
418 (nodeList->getLength() == 1 &&
419 currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE))
422 std::cout << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
425 *out << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
431 auto end = std::chrono::high_resolution_clock::now();
433 std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
434 __COUTT__ << tabStr << XML_TO_CHAR(currEl->getNodeName()) <<
" -- DONE Time taken to call recurse xml out = " << duration <<
" milliseconds." << std::endl;
444 const unsigned int occurance)
446 unsigned int count = 0;
447 return recursiveFindElementValue(
448 theDocument_->getDocumentElement(), field, occurance, count);
454 std::string HttpXmlDocument::recursiveFindElementValue(xercesc::DOMElement* currEl,
455 const std::string& field,
456 const unsigned int occurance,
459 if(XML_TO_CHAR(currEl->getNodeName()) == field &&
460 occurance == count++)
462 if(currEl->getFirstChild() != NULL &&
463 currEl->getFirstChild()->getNodeType() ==
464 xercesc::DOMNode::TEXT_NODE)
467 XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()));
474 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
475 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
476 if(nodeList->item(i)->getNodeType() !=
477 xercesc::DOMNode::TEXT_NODE)
479 retStr = recursiveFindElementValue(
480 (xercesc::DOMElement*)(nodeList->item(i)), field, occurance, count);
493 std::vector<std::string>& retVec)
495 recursiveFindAllElements(theDocument_->getDocumentElement(), field, &retVec);
501 void HttpXmlDocument::recursiveFindAllElements(xercesc::DOMElement* currEl,
502 const std::string& field,
503 std::vector<std::string>* retVec)
505 if(XML_TO_CHAR(currEl->getNodeName()) == field && currEl->getFirstChild() != NULL &&
506 currEl->getFirstChild()->getNodeType() ==
507 xercesc::DOMNode::TEXT_NODE)
509 retVec->push_back(XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()));
512 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
513 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
514 if(nodeList->item(i)->getNodeType() !=
515 xercesc::DOMNode::TEXT_NODE)
516 recursiveFindAllElements(
517 (xercesc::DOMElement*)(nodeList->item(i)), field, retVec);
525 const unsigned int occurance)
528 theDocument_->getDocumentElement(), field, occurance);
537 xercesc::DOMElement* parentEl,
const std::string& field,
const unsigned int occurance)
539 unsigned int count = 0;
540 return recursiveFindElement(parentEl, field, occurance, count);
546 xercesc::DOMElement* HttpXmlDocument::recursiveFindElement(xercesc::DOMElement* currEl,
547 const std::string& field,
548 const unsigned int occurance,
551 if(XML_TO_CHAR(currEl->getNodeName()) == field &&
552 occurance == count++)
554 if(currEl->getFirstChild() != NULL &&
555 currEl->getFirstChild()->getNodeType() ==
556 xercesc::DOMNode::TEXT_NODE)
563 xercesc::DOMElement* retEl;
565 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
566 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
567 if(nodeList->item(i)->getNodeType() !=
568 xercesc::DOMNode::TEXT_NODE)
570 retEl = recursiveFindElement(
571 (xercesc::DOMElement*)(nodeList->item(i)), field, occurance, count);
583 void HttpXmlDocument::recursiveAddElementToParent(xercesc::DOMElement* child,
584 xercesc::DOMElement* parent,
587 std::string childText =
"";
589 std::string childName =
590 XML_TO_CHAR(child->getNodeName());
592 if(child->getFirstChild() != NULL &&
593 child->getFirstChild()->getNodeType() ==
597 childText = XML_TO_CHAR(child->getFirstChild()->getNodeValue());
601 __COUTS__(20) <<
"pre escape childText " << childText << std::endl;
603 __COUTS__(20) <<
"post escape childText " << childText << std::endl;
606 __COUTS__(20) <<
"childName " << childName <<
" childText " << childText << std::endl;
612 xercesc::DOMNodeList* nodeList = child->getChildNodes();
613 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
615 if(nodeList->item(i)->getNodeType() ==
616 xercesc::DOMNode::TEXT_NODE)
619 recursiveAddElementToParent(
620 (xercesc::DOMElement*)(nodeList->item(i)), newParent, html);
629 std::vector<xercesc::DOMElement*>& retVec)
631 recursiveFindAllElements(theDocument_->getDocumentElement(), field, &retVec);
637 void HttpXmlDocument::recursiveFindAllElements(xercesc::DOMElement* currEl,
638 const std::string& field,
639 std::vector<xercesc::DOMElement*>* retVec)
641 if(XML_TO_CHAR(currEl->getNodeName()) == field && currEl->getFirstChild() != NULL &&
642 currEl->getFirstChild()->getNodeType() ==
643 xercesc::DOMNode::TEXT_NODE)
645 retVec->push_back(currEl);
648 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
649 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
650 if(nodeList->item(i)->getNodeType() !=
651 xercesc::DOMNode::TEXT_NODE)
652 recursiveFindAllElements(
653 (xercesc::DOMElement*)(nodeList->item(i)), field, retVec);
664 struct stat fileStatus;
666 if(stat(filePath.c_str(), &fileStatus) != 0)
677 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
679 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
680 parser->setDoNamespaces(
true);
681 parser->setDoSchema(
true);
682 parser->useCachedGrammarInParse(
false);
686 parser->parse(filePath.c_str());
689 theDocument_ = parser->adoptDocument();
694 rootElement_ = theDocument_->getDocumentElement();
697 __SS__ <<
"empty XML theDocument_: " << filePath << std::endl;
699 throw(std::runtime_error(
"empty XML theDocument_"));
702 recursiveFixTextFields(
705 xercesc::DOMNodeList* nodeList =
706 theDocument_->getElementsByTagName(CONVERT_TO_XML(headerTagName_));
707 if(nodeList->getLength())
709 (xercesc::DOMElement*)(theDocument_
710 ->getElementsByTagName(
711 CONVERT_TO_XML(headerTagName_))
716 dataElement_ = (xercesc::DOMElement*)(theDocument_
717 ->getElementsByTagName(
718 CONVERT_TO_XML(dataTagName_))
721 catch(xercesc::XMLException& e)
723 __SS__ <<
"Error parsing file: " << filePath << std::endl;
725 __COUT__ <<
"Error parsing file." << std::endl;
736 void HttpXmlDocument::recursiveFixTextFields(xercesc::DOMElement* currEl)
738 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
741 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
742 if(nodeList->item(i)->getNodeType() ==
743 xercesc::DOMNode::TEXT_NODE)
744 ((xercesc::DOMElement*)(nodeList->item(i)))
745 ->setTextContent(CONVERT_TO_XML(
747 ((xercesc::DOMElement*)(nodeList->item(i)))->getNodeValue()))));
749 recursiveFixTextFields((xercesc::DOMElement*)(nodeList->item(i)));
xercesc::DOMElement * getMatchingElement(const std::string &field, const unsigned int occurance=0)
void getAllMatchingValues(const std::string &field, std::vector< std::string > &retVec)
HttpXmlDocument(std::string cookieCode="", std::string displayName="")
xercesc::DOMElement * getMatchingElementInSubtree(xercesc::DOMElement *currEl, const std::string &field, const unsigned int occurance=0)
void copyDataChildren(HttpXmlDocument &document)
void removeDataElement(unsigned int dataChildIndex=0)
default to first child
bool loadXmlDocument(const std::string &filePath)
unsigned int getChildrenCount(xercesc::DOMElement *parent=0)
std::string getMatchingValue(const std::string &field, const unsigned int occurance=0)
void outputXmlDocument(std::ostringstream *out, bool dispStdOut=false, bool allowWhiteSpace=false, bool printErrors=false)
void getAllMatchingElements(const std::string &field, std::vector< xercesc::DOMElement * > &retVec)
Note that XmlDocument functionality is extended by HttpXmlDocument class.
xercesc::DOMElement * addTextElementToParent(const std::string &childName, const std::string &childText, xercesc::DOMElement *parent)
void recursiveRemoveChild(xercesc::DOMElement *childEl, xercesc::DOMElement *parentEl)
defines used also by OtsConfigurationWizardSupervisor
static std::string escapeString(std::string inString, bool allowWhiteSpace=false, bool forHtml=false)