1 #include "otsdaq/XmlUtilities/XmlDocument.h"
2 #include "otsdaq/Macros/CoutMacros.h"
3 #include "otsdaq/Macros/MessageTools.h"
4 #include "otsdaq/Macros/StringMacros.h"
5 #include "otsdaq/MessageFacility/MessageFacility.h"
6 #include "otsdaq/XmlUtilities/ConvertFromXML.h"
7 #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>
17 #include <xercesc/parsers/XercesDOMParser.hpp>
20 #include <xercesc/dom/DOMNodeIterator.hpp>
21 #include <xercesc/dom/DOMNodeList.hpp>
22 #include <xercesc/dom/DOMText.hpp>
23 #include <xercesc/validators/common/Grammar.hpp>
25 #include <xercesc/parsers/XercesDOMParser.hpp>
26 #include <xercesc/util/XMLUni.hpp>
27 #include <xercesc/util/XercesDefs.hpp>
29 #include <xercesc/framework/LocalFileFormatTarget.hpp>
30 #include <xercesc/util/OutOfMemoryException.hpp>
32 #include <boost/regex.hpp>
40 #include <sys/types.h>
48 __COUTS__(50) <<
"in" << std::endl;
51 rootElement_ = theDocument_->getDocumentElement();
52 __COUTS__(50) <<
"out" << std::endl;
58 __COUTS__(50) <<
"in" << std::endl;
60 __COUTS__(50) <<
"out" << std::endl;
66 __COUTS__(50) <<
"in" << std::endl;
68 rootElement_ = theDocument_->getDocumentElement();
69 recursiveElementCopy(doc.rootElement_, rootElement_);
70 __COUTS__(50) <<
"out" << std::endl;
75 XmlDocument::~XmlDocument(
void)
77 __COUTS__(50) <<
"Xml Destructor" << std::endl;
82 void XmlDocument::initDocument(
void)
87 xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"Core"));
89 if(theImplementation_)
93 theDocument_ = theImplementation_->createDocument(
94 CONVERT_TO_XML(
"http://www.w3.org/2001/XMLSchema-instance"),
98 CONVERT_TO_XML(rootTagName_),
101 catch(
const xercesc::OutOfMemoryException&)
103 __SS__ <<
"OutOfMemoryException" << __E__;
106 catch(
const xercesc::DOMException& e)
108 __SS__ <<
"DOMException code is: " << e.code << __E__;
111 catch(
const xercesc::XMLException& e)
113 __SS__ <<
"Error Message: " << XML_TO_CHAR(e.getMessage()) << __E__;
118 __SS__ <<
"An error occurred creating the theDocument_" << __E__;
123 catch(
const std::exception& e)
125 ss <<
"Exception message: " << e.what();
135 __SS__ <<
"Requested theImplementation_ is not supported" << __E__;
138 darioXMLStyle_ =
false;
139 isALeaf_[
true] =
"true";
140 isALeaf_[
false] =
"false";
144 void XmlDocument::initPlatform(
void)
148 xercesc::XMLPlatformUtils::Initialize();
152 catch(xercesc::XMLException& e)
154 __COUT__ <<
"XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage())
160 void XmlDocument::terminatePlatform(
void)
164 __COUTS__(50) <<
"Releasing the document" << std::endl;
165 theDocument_->release();
166 __COUTS__(50) <<
"document released" << std::endl;
170 XERCES_STD_QUALIFIER cerr <<
"An error occurred destroying the theDocument_"
171 << XERCES_STD_QUALIFIER endl;
176 xercesc::XMLPlatformUtils::Terminate();
178 catch(xercesc::XMLException& e)
180 __COUT__ <<
"XML toolkit teardown error: " << XML_TO_CHAR(e.getMessage())
186 xercesc::DOMElement* XmlDocument::createChildElement(
const std::string& childClass,
187 xercesc::DOMElement* parent)
189 if(parent ==
nullptr)
191 __SS__ <<
"Illegal Null Parent Pointer!" << __E__;
194 xercesc::DOMElement* child =
nullptr;
197 child = theDocument_->createElement(CONVERT_TO_XML(childClass));
199 catch(xercesc::DOMException& e)
201 __COUT__ <<
"Can't use the class: " << childClass
202 <<
" to create the child element because the exception says: "
203 << XML_TO_CHAR(e.getMessage())
204 <<
". Very likely you have a name that starts with a number and that's "
208 parent->appendChild(child);
213 xercesc::DOMElement* XmlDocument::addAttributeToNode(
const std::string& attributeName,
214 const std::string& attributeValue,
215 xercesc::DOMElement* node)
219 __SS__ <<
"Illegal Null Parent Pointer!" << __E__;
225 node->setAttribute(CONVERT_TO_XML(attributeName), CONVERT_TO_XML(attributeValue));
227 catch(xercesc::DOMException& e)
229 __COUT__ <<
"Can't use the name: " << attributeName
230 <<
" to create the attribute because the exception says: "
231 << XML_TO_CHAR(e.getMessage())
232 <<
". Very likely you have a name that starts with a number and that's "
245 const std::string& childText,
246 xercesc::DOMElement* parent)
248 if(parent ==
nullptr)
250 __SS__ <<
"Illegal Null Parent Pointer!" << __E__;
253 xercesc::DOMElement* child =
nullptr;
256 child = theDocument_->createElement(CONVERT_TO_XML(childName));
258 catch(xercesc::DOMException& e)
260 __COUT__ <<
"Can't use the name: " << childName
261 <<
" to create the child element because the exception says: "
262 << XML_TO_CHAR(e.getMessage())
263 <<
". Very likely you have a name that starts with a number and that's "
267 parent->appendChild(child);
271 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(childText)));
276 __COUT_ERR__ <<
"Error caught attempting to create a text node for this text: "
277 << childText <<
". Converting instead to 'Illegal text..'"
279 child->appendChild(theDocument_->createTextNode(
280 CONVERT_TO_XML(
"Illegal text content blocked.")));
291 const std::string& childText,
292 const std::string& parentName,
293 unsigned int parentIndex)
295 xercesc::DOMNodeList* nodeList =
296 theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName));
298 if(parentIndex >= nodeList->getLength())
300 __COUT__ <<
"WARNING: Illegal parent index attempted in tags with name: "
301 << parentName <<
", index: " << parentIndex << std::endl;
306 childName, childText, (xercesc::DOMElement*)(nodeList->item(parentIndex)));
311 xercesc::DOMDocument* copy)
313 recursiveElementCopy(toCopy->getDocumentElement(), copy->getDocumentElement());
317 void XmlDocument::recursiveElementCopy(
const xercesc::DOMElement* toCopy,
318 xercesc::DOMElement* copy)
320 xercesc::DOMNodeList* nodeListToCopy =
321 toCopy->getChildNodes();
322 xercesc::DOMNode* iNode;
323 xercesc::DOMDocument*
copyDocument = copy->getOwnerDocument();
324 for(
unsigned int i = 0; i < nodeListToCopy->getLength(); i++)
326 iNode = nodeListToCopy->item(i);
327 xercesc::DOMElement* child =
copyDocument->createElement(iNode->getNodeName());
328 copy->appendChild(child);
329 if(child->getFirstChild() != NULL)
331 if(iNode->getFirstChild() != 0 &&
332 iNode->getFirstChild()->getNodeType() ==
333 xercesc::DOMNode::TEXT_NODE)
337 copyDocument->createTextNode(child->getFirstChild()->getNodeValue()));
339 recursiveElementCopy((xercesc::DOMElement*)(iNode), child);
354 void XmlDocument::setDocument(xercesc::DOMDocument* doc) { theDocument_ = doc; }
359 std::ostringstream* out,
361 const std::string& tabStr)
366 __COUT__ << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
370 *out << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
374 if(currEl->getFirstChild() != NULL &&
375 currEl->getFirstChild()->getNodeType() ==
376 xercesc::DOMNode::TEXT_NODE)
380 std::cout <<
" value='"
382 XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()),
true)
387 XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()),
true)
391 xercesc::DOMNamedNodeMap* attrList = currEl->getAttributes();
394 for(XMLSize_t ii = 0; ii < attrList->getLength(); ++ii)
397 std::cout <<
" " << XML_TO_CHAR(attrList->item(ii)->getNodeName()) <<
"='"
399 XML_TO_CHAR(attrList->item(ii)->getNodeValue()),
true)
402 *out <<
" " << XML_TO_CHAR(attrList->item(ii)->getNodeName()) <<
"='"
404 XML_TO_CHAR(attrList->item(ii)->getNodeValue()),
true)
409 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
413 std::cout << ((nodeList->getLength() == 0 ||
414 (nodeList->getLength() == 1 &&
415 currEl->getFirstChild()->getNodeType() ==
416 xercesc::DOMNode::TEXT_NODE))
421 *out << ((nodeList->getLength() == 0 ||
422 (nodeList->getLength() == 1 &&
423 currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))
429 std::string newTabStr = tabStr +
"\t";
430 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
431 if(nodeList->item(i)->getNodeType() !=
432 xercesc::DOMNode::TEXT_NODE)
434 (xercesc::DOMElement*)(nodeList->item(i)), out, dispStdOut, newTabStr);
437 if(nodeList->getLength() > 1 ||
438 (nodeList->getLength() == 1 &&
439 currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE))
442 __COUT__ << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
445 *out << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
454 xercesc::DOMElement* parentEl)
457 xercesc::DOMNodeList* nodeList =
458 childEl->getChildNodes();
459 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
461 (xercesc::DOMElement*)(nodeList->item(nodeList->getLength() - 1 - i)),
465 parentEl->removeChild(childEl);
475 __COUT__ <<
"Saving theDocument_ to file: " << filePath << std::endl;
480 xercesc::DOMImplementation* saveImplementation =
481 xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"LS"));
483 __COUTT__ <<
"XERCES Version: " << _XERCES_VERSION << std::endl;
485 #if _XERCES_VERSION >= 30000
490 xercesc::DOMLSSerializer* serializer =
491 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSSerializer();
494 if(serializer->getDomConfig()->canSetParameter(
495 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true))
496 serializer->getDomConfig()->setParameter(
497 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
500 serializer->setNewLine(CONVERT_TO_XML(
"\r\n"));
506 xercesc::XMLFormatTarget* formatTarget;
510 formatTarget =
new xercesc::LocalFileFormatTarget(filePath.c_str());
514 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
515 serializer->release();
522 xercesc::DOMLSOutput* output =
523 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSOutput();
526 output->setByteStream(formatTarget);
528 serializer->write(theDocument_, output);
529 serializer->release();
534 xercesc::DOMWriter* serializer =
535 ((xercesc::DOMImplementationLS*)saveImplementation)->createDOMWriter();
536 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
547 XMLCh* tempFilePath = xercesc::XMLString::transcode(filePath.c_str());
548 xercesc::XMLFormatTarget* formatTarget;
551 formatTarget =
new xercesc::LocalFileFormatTarget(tempFilePath);
555 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
556 serializer->release();
557 xercesc::XMLString::release(&tempFilePath);
563 serializer->writeNode(formatTarget, *theDocument_);
564 serializer->release();
565 xercesc::XMLString::release(&tempFilePath);
570 __COUTS__(50) <<
"delete format target" << std::endl;
572 #if _XERCES_VERSION >= 30000
574 __COUTS__(50) <<
"delete output0" << std::endl;
576 __COUTS__(50) <<
"delete output1" << std::endl;
582 bool XmlDocument::loadXmlDocument(
const std::string& filePath)
584 __COUT__ <<
"Loading theDocument_ from file: " << filePath << std::endl;
586 struct stat fileStatus;
588 if(stat(filePath.c_str(), &fileStatus) != 0)
590 __COUT__ <<
"File not accessible." << std::endl;
597 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
598 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
599 parser->setDoNamespaces(
true);
600 parser->setDoSchema(
true);
601 parser->useCachedGrammarInParse(
false);
605 parser->parse(filePath.c_str());
608 theDocument_ = parser->adoptDocument();
613 rootElement_ = theDocument_->getDocumentElement();
615 throw(std::runtime_error(
"empty XML theDocument_"));
617 catch(xercesc::XMLException& e)
619 __COUT__ <<
"Error parsing file." << std::endl;
628 void XmlDocument::setAnchors(
const std::string& fSystemPath,
const std::string& fRootPath)
630 fSystemPath_ = fSystemPath;
631 fRootPath_ = fRootPath;
635 void XmlDocument::makeDirectoryBinaryTree(
const std::string& fSystemPath,
636 const std::string& fRootPath,
638 xercesc::DOMElement* anchorNode)
641 struct dirent* entry;
643 std::string newFullPath =
"";
647 fSystemPath_ = fSystemPath;
648 fRootPath_ = fRootPath;
650 std::string fullPathName =
651 fSystemPath_ + std::string(
"/") + fRootPath_ + std::string(
"/") + fFoldersPath_;
654 anchorNode = rootElement_;
656 if(!(dir = opendir(fullPathName.c_str())))
659 while((entry = readdir(dir)) != NULL)
661 std::string sName = std::string(entry->d_name);
663 if(sName.size() == 2)
665 if(((sName.size() == 1) && fchar ==
'.') || ((sName.size() == 2) && schar ==
'.'))
670 if(entry->d_type == DT_DIR)
672 fThisFolderPath_ = std::string(entry->d_name);
673 newFullPath = fSystemPath_ + fRootPath + std::string(
"/") + fThisFolderPath_;
674 hierarchyPaths_.push_back(std::string(entry->d_name) + std::string(
""));
675 fFoldersPath_ += hierarchyPaths_.back() +
"/";
676 xercesc::DOMElement* node = this->populateBinaryTreeNode(
677 anchorNode, std::string(entry->d_name), indent,
false);
678 this->makeDirectoryBinaryTree(fSystemPath, fRootPath, indent + 1, node);
679 if(hierarchyPaths_.size() > 0)
680 hierarchyPaths_.pop_back();
681 if(hierarchyPaths_.size() > 0)
683 fFoldersPath_ = hierarchyPaths_.back() +
"/";
692 newFullPath = fSystemPath_ + std::string(
"/") + std::string(entry->d_name);
694 boost::regex re{
".*\\.root$"};
695 if(boost::regex_search(newFullPath, what, re))
697 fFileName_ = std::string(entry->d_name);
699 for(
unsigned int i = 0; i < hierarchyPaths_.size(); ++i)
701 fFoldersPath_ += hierarchyPaths_[i] + std::string(
"/");
703 this->populateBinaryTreeNode(anchorNode, fFileName_, indent,
true);
711 xercesc::DOMElement* XmlDocument::populateBinaryTreeNode(xercesc::DOMElement* anchorNode,
712 const std::string& name,
716 std::string nm =
"unassigned";
717 xercesc::DOMElement* nodes = NULL;
729 if(theNodes_.find(indent) != theNodes_.end())
731 if(theNodes_.find(indent) != theNodes_.end())
732 nodes = theNodes_.find(indent)->second;
733 if(theNames_.find(indent) != theNames_.end())
734 nm = theNames_.find(indent)->second;
738 nodes = theDocument_->createElement(xercesc::XMLString::transcode(
"nodes"));
739 theNodes_[indent] = nodes;
740 theNames_[indent] = name;
741 anchorNode->appendChild(nodes);
744 xercesc::DOMElement* node =
745 theDocument_->createElement(xercesc::XMLString::transcode(
"node"));
746 nodes->appendChild(node);
748 xercesc::DOMElement* nChilds =
749 theDocument_->createElement(xercesc::XMLString::transcode(
"nChilds"));
750 node->appendChild(nChilds);
752 xercesc::DOMText* nChildsVal =
753 theDocument_->createTextNode(xercesc::XMLString::transcode(
"x"));
754 nChilds->appendChild(nChildsVal);
756 xercesc::DOMElement* fSystemPathNode =
757 theDocument_->createElement(xercesc::XMLString::transcode(
"fSystemPath"));
758 node->appendChild(fSystemPathNode);
760 xercesc::DOMText* fSystemPathVal =
761 theDocument_->createTextNode(xercesc::XMLString::transcode(fSystemPath_.c_str()));
762 fSystemPathNode->appendChild(fSystemPathVal);
764 xercesc::DOMElement* fRootPathNode =
765 theDocument_->createElement(xercesc::XMLString::transcode(
"fRootPath"));
766 node->appendChild(fRootPathNode);
768 xercesc::DOMText* fRootPathVal =
769 theDocument_->createTextNode(xercesc::XMLString::transcode(fRootPath_.c_str()));
770 fRootPathNode->appendChild(fRootPathVal);
772 xercesc::DOMElement* fFoldersPathNode =
773 theDocument_->createElement(xercesc::XMLString::transcode(
"fFoldersPath"));
774 node->appendChild(fFoldersPathNode);
776 xercesc::DOMText* foldersPathVal = theDocument_->createTextNode(
777 xercesc::XMLString::transcode(fFoldersPath_.c_str()));
778 fFoldersPathNode->appendChild(foldersPathVal);
780 xercesc::DOMElement* fThisFolderPath = NULL;
781 xercesc::DOMElement* fFileOrHistName = NULL;
782 xercesc::DOMText* fileOrDirNameVal = NULL;
783 xercesc::DOMText* thisFolderNameVal = NULL;
786 theDocument_->createElement(xercesc::XMLString::transcode(
"fDisplayName"));
791 theDocument_->createElement(xercesc::XMLString::transcode(
"fFileName"));
793 theDocument_->createTextNode(xercesc::XMLString::transcode(name.c_str()));
795 theDocument_->createTextNode(xercesc::XMLString::transcode(name.c_str()));
797 ss_ <<
"name: " << ACRed << name << ACPlain <<
"/" << ACGreen << name;
798 STDLINE(ss_.str(),
"");
804 theDocument_->createElement(xercesc::XMLString::transcode(
"fFileName"));
806 theDocument_->createTextNode(xercesc::XMLString::transcode(blank.c_str()));
807 thisFolderNameVal = theDocument_->createTextNode(
808 xercesc::XMLString::transcode(fThisFolderPath_.c_str()));
810 ss_ <<
"name: " << ACRed << fThisFolderPath_ << ACPlain <<
"/" << ACGreen << name;
811 STDLINE(ss_.str(),
"");
814 node->appendChild(fFileOrHistName);
815 fFileOrHistName->appendChild(fileOrDirNameVal);
817 node->appendChild(fThisFolderPath);
818 fThisFolderPath->appendChild(thisFolderNameVal);
820 xercesc::DOMElement* leaf =
821 theDocument_->createElement(xercesc::XMLString::transcode(
"leaf"));
822 node->appendChild(leaf);
824 xercesc::DOMText* leafVal = theDocument_->createTextNode(
825 xercesc::XMLString::transcode(isALeaf_[isLeaf].c_str()));
826 leaf->appendChild(leafVal);
835 darioXMLStyle_ = darioStyle;
Note that XmlDocument functionality is extended by HttpXmlDocument class.
xercesc::DOMElement * addTextElementToParent(const std::string &childName, const std::string &childText, xercesc::DOMElement *parent)
void copyDocument(const xercesc::DOMDocument *toCopy, xercesc::DOMDocument *copy)
void recursiveRemoveChild(xercesc::DOMElement *childEl, xercesc::DOMElement *parentEl)
void setDarioStyle(bool darioStyle)
Used by developer Dario Menasce for alternative XML requests at web user interface.
XmlDocument(const std::string &rootName="ROOT")
void saveXmlDocument(const std::string &filePath)
void outputXmlDocument(std::ostringstream *out, bool dispStdOut=false)
void recursiveOutputXmlDocument(xercesc::DOMElement *currEl, std::ostringstream *out, bool dispStdOut=false, const std::string &tabStr="")
static std::string escapeString(std::string inString, bool allowWhiteSpace=false)
static std::string stackTrace(void)