1 #include "otsdaq/XmlUtilities/XmlDocument.h"
2 #include "otsdaq/Macros/CoutMacros.h"
3 #include "otsdaq/Macros/MessageTools.h"
4 #include "otsdaq/MessageFacility/MessageFacility.h"
5 #include "otsdaq/XmlUtilities/ConvertFromXML.h"
6 #include "otsdaq/XmlUtilities/ConvertToXML.h"
9 #include <xercesc/dom/DOM.hpp>
10 #include <xercesc/dom/DOMDocument.hpp>
11 #include <xercesc/dom/DOMDocumentType.hpp>
12 #include <xercesc/dom/DOMElement.hpp>
13 #include <xercesc/dom/DOMImplementation.hpp>
14 #include <xercesc/dom/DOMImplementationLS.hpp>
15 #include <xercesc/dom/DOMImplementationRegistry.hpp>
16 #include <xercesc/parsers/XercesDOMParser.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>
31 #include <boost/regex.hpp>
39 #include <sys/types.h>
45 XmlDocument::XmlDocument(std::string rootName) : rootTagName_(rootName)
50 rootElement_ = theDocument_->getDocumentElement();
55 XmlDocument::XmlDocument(
const XmlDocument& doc) : rootTagName_(doc.rootTagName_)
65 __COUT__ <<
"in" << std::endl;
67 rootElement_ = theDocument_->getDocumentElement();
68 recursiveElementCopy(doc.rootElement_, rootElement_);
69 __COUT__ <<
"out" << std::endl;
74 XmlDocument::~XmlDocument(
void)
81 void XmlDocument::initDocument(
void)
85 theImplementation_ = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"Core"));
87 if (theImplementation_)
91 theDocument_ = theImplementation_->createDocument(CONVERT_TO_XML(
"http://www.w3.org/2001/XMLSchema-instance"),
95 CONVERT_TO_XML(rootTagName_),
98 catch (
const xercesc::OutOfMemoryException&)
100 XERCES_STD_QUALIFIER cerr <<
"OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
102 catch (
const xercesc::DOMException & e)
104 XERCES_STD_QUALIFIER cerr <<
"DOMException code is: " << e.code << XERCES_STD_QUALIFIER endl;
106 catch (
const xercesc::XMLException & e)
108 __COUT__ <<
"Error Message: " << XML_TO_CHAR(e.getMessage()) << std::endl;
112 XERCES_STD_QUALIFIER cerr <<
"An error occurred creating the theDocument_" << XERCES_STD_QUALIFIER endl;
116 XERCES_STD_QUALIFIER cerr <<
"Requested theImplementation_ is not supported" << XERCES_STD_QUALIFIER endl;
117 darioXMLStyle_ =
false;
118 isALeaf_[
true] =
"true";
119 isALeaf_[
false] =
"false";
123 void XmlDocument::initPlatform(
void)
127 xercesc::XMLPlatformUtils::Initialize();
131 catch (xercesc::XMLException & e)
133 __COUT__ <<
"XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
138 void XmlDocument::terminatePlatform(
void)
143 theDocument_->release();
148 XERCES_STD_QUALIFIER cerr <<
"An error occurred destroying the theDocument_" << XERCES_STD_QUALIFIER endl;
153 xercesc::XMLPlatformUtils::Terminate();
155 catch (xercesc::XMLException & e)
157 __COUT__ <<
"XML toolkit teardown error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
166 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName, std::string childText, xercesc::DOMElement* parent)
170 __SS__ <<
"Illegal Null Parent Pointer!" << __E__;
174 xercesc::DOMElement* child =
nullptr;
177 child = theDocument_->createElement(CONVERT_TO_XML(childName));
179 catch (xercesc::DOMException & e)
181 __COUT__ <<
"Can't use the name: " << childName <<
" to create the child element because the exception says: " << XML_TO_CHAR(e.getMessage())
182 <<
". Very likely you have a name that starts with a number and that's "
186 parent->appendChild(child);
190 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(childText)));
194 __COUT_ERR__ <<
"Error caught attempting to create a text node for this text: " << childText <<
". Converting instead to 'Illegal text..'" << std::endl;
195 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(
"Illegal text content blocked.")));
205 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName, std::string childText, std::string parentName,
unsigned int parentIndex)
207 xercesc::DOMNodeList* nodeList = theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName));
209 if (parentIndex >= nodeList->getLength())
211 __COUT__ <<
"WARNING: Illegal parent index attempted in tags with name: " << parentName <<
", index: " << parentIndex << std::endl;
215 return addTextElementToParent(childName, childText, (xercesc::DOMElement*)(nodeList->item(parentIndex)));
219 void XmlDocument::copyDocument(
const xercesc::DOMDocument* toCopy, xercesc::DOMDocument* copy)
221 recursiveElementCopy(toCopy->getDocumentElement(), copy->getDocumentElement());
225 void XmlDocument::recursiveElementCopy(
const xercesc::DOMElement* toCopy, xercesc::DOMElement* copy)
227 xercesc::DOMNodeList* nodeListToCopy = toCopy->getChildNodes();
228 xercesc::DOMNode* iNode;
229 xercesc::DOMDocument* copyDocument = copy->getOwnerDocument();
230 for (
unsigned int i = 0; i < nodeListToCopy->getLength(); i++)
232 iNode = nodeListToCopy->item(i);
233 xercesc::DOMElement* child = copyDocument->createElement(iNode->getNodeName());
234 copy->appendChild(child);
235 if (child->getFirstChild() != NULL)
237 if (iNode->getFirstChild() != 0 &&
238 iNode->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)
241 child->appendChild(copyDocument->createTextNode(child->getFirstChild()->getNodeValue()));
243 recursiveElementCopy((xercesc::DOMElement*)(iNode), child);
428 void XmlDocument::outputXmlDocument(std::ostringstream* out,
bool dispStdOut)
430 recursiveOutputXmlDocument(theDocument_->getDocumentElement(), out, dispStdOut);
434 void XmlDocument::setDocument(xercesc::DOMDocument* doc) { theDocument_ = doc; }
438 void XmlDocument::recursiveOutputXmlDocument(xercesc::DOMElement* currEl, std::ostringstream* out,
bool dispStdOut, std::string tabStr)
443 __COUT__ << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
447 *out << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
451 if (currEl->getFirstChild() != NULL && currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)
455 std::cout <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
457 *out <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
460 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
464 std::cout << ((nodeList->getLength() == 0 || (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))
469 *out << ((nodeList->getLength() == 0 || (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)) ?
"/"
474 std::string newTabStr = tabStr +
"\t";
475 for (
unsigned int i = 0; i < nodeList->getLength(); ++i)
476 if (nodeList->item(i)->getNodeType() != xercesc::DOMNode::TEXT_NODE)
477 recursiveOutputXmlDocument((xercesc::DOMElement*)(nodeList->item(i)), out, dispStdOut, newTabStr);
480 if (nodeList->getLength() > 1 || (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE))
483 __COUT__ << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">" << std::endl;
485 *out << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">" << std::endl;
575 std::string XmlDocument::escapeString(std::string inString,
bool allowWhiteSpace)
579 unsigned int ws = -1;
582 for (
unsigned int i = 0; i < inString.length(); i++)
583 if (inString[i] !=
' ')
586 __COUT__ << inString[i] <<
":" << (int)inString[i] <<
":" << inString << std::endl;
589 if (inString[i] ==
'\r' || inString[i] ==
'\n' ||
590 inString[i] ==
'\t' ||
593 (inString[i] >
char(126) && inString[i] < char(161)))
604 sprintf(htmlTmp,
"&#%3.3d", inString[i]);
605 inString.insert(i, htmlTmp);
606 inString.replace(i + 5, 1, 1,
';');
621 sprintf(htmlTmp,
"        ");
622 inString.insert(i, htmlTmp);
623 inString.replace(i + 47, 1, 1,
';');
629 sprintf(htmlTmp,
"	");
630 inString.insert(i, htmlTmp);
631 inString.replace(i + 5, 1, 1,
';');
641 inString.erase(i, 1);
645 __COUT__ << inString << std::endl;
650 __COUT__ << inString << std::endl;
653 if (inString[i] ==
'\"' || inString[i] ==
'\'')
656 (inString[i] ==
'\'') ?
"&apos" :
""");
657 inString.replace(i + 5, 1, 1,
';');
661 else if (inString[i] ==
'&')
663 inString.insert(i,
"&");
664 inString.replace(i + 4, 1, 1,
';');
667 else if (inString[i] ==
'<' || inString[i] ==
'>')
670 (inString[i] ==
'<') ?
"<" :
">");
671 inString.replace(i + 3, 1, 1,
';');
674 else if (inString[i] >=
char(161) && inString[i] <=
char(255))
676 sprintf(htmlTmp,
"&#%3.3d", inString[i]);
677 inString.insert(i, htmlTmp);
678 inString.replace(i + 5, 1, 1,
';');
683 __COUT__ << inString << std::endl;
687 else if (allowWhiteSpace)
693 if (0 && i - 2 == ws)
695 inString.insert(i,
" ");
698 inString.insert(i,
" ");
699 inString.replace(i + 5, 1, 1,
';');
705 __COUT__ << inString.size() <<
" " << ws << std::endl;
710 __COUT__ << inString.size() <<
" " << inString << std::endl;
716 if (ws == (
unsigned int)-1)
718 return inString.substr(0, ws + 1);
724 void XmlDocument::recursiveRemoveChild(xercesc::DOMElement* childEl, xercesc::DOMElement* parentEl)
727 xercesc::DOMNodeList* nodeList = childEl->getChildNodes();
728 for (
unsigned int i = 0; i < nodeList->getLength(); ++i)
729 recursiveRemoveChild((xercesc::DOMElement*)(nodeList->item(nodeList->getLength() - 1 - i)), childEl);
732 parentEl->removeChild(childEl);
740 void XmlDocument::saveXmlDocument(std::string filePath)
742 __COUT__ <<
"Saving theDocument_ to file: " << filePath << std::endl;
747 xercesc::DOMImplementation* saveImplementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"LS"));
751 #if _XERCES_VERSION >= 30000
756 xercesc::DOMLSSerializer* serializer = ((xercesc::DOMImplementationLS*)saveImplementation)->createLSSerializer();
759 if (serializer->getDomConfig()->canSetParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true))
760 serializer->getDomConfig()->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
763 serializer->setNewLine(CONVERT_TO_XML(
"\r\n"));
769 xercesc::XMLFormatTarget* formatTarget;
773 formatTarget =
new xercesc::LocalFileFormatTarget(filePath.c_str());
777 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
778 serializer->release();
785 xercesc::DOMLSOutput* output = ((xercesc::DOMImplementationLS*)saveImplementation)->createLSOutput();
788 output->setByteStream(formatTarget);
790 serializer->write(theDocument_, output);
791 serializer->release();
796 xercesc::DOMWriter* serializer = ((xercesc::DOMImplementationLS*)saveImplementation)->createDOMWriter();
797 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
808 XMLCh* tempFilePath = xercesc::XMLString::transcode(filePath.c_str());
809 xercesc::XMLFormatTarget* formatTarget;
812 formatTarget =
new xercesc::LocalFileFormatTarget(tempFilePath);
816 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
817 serializer->release();
818 xercesc::XMLString::release(&tempFilePath);
824 serializer->writeNode(formatTarget, *theDocument_);
825 serializer->release();
826 xercesc::XMLString::release(&tempFilePath);
833 #if _XERCES_VERSION >= 30000
843 bool XmlDocument::loadXmlDocument(std::string filePath)
845 __COUT__ <<
"Loading theDocument_ from file: " << filePath << std::endl;
847 struct stat fileStatus;
849 if (stat(filePath.c_str(), &fileStatus) != 0)
851 __COUT__ <<
"File not accessible." << std::endl;
858 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
859 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
860 parser->setDoNamespaces(
true);
861 parser->setDoSchema(
true);
862 parser->useCachedGrammarInParse(
false);
866 parser->parse(filePath.c_str());
869 theDocument_ = parser->adoptDocument();
874 rootElement_ = theDocument_->getDocumentElement();
876 throw(std::runtime_error(
"empty XML theDocument_"));
878 catch (xercesc::XMLException & e)
880 __COUT__ <<
"Error parsing file." << std::endl;
889 void XmlDocument::setAnchors(std::string fSystemPath,
890 std::string fRootPath)
892 fSystemPath_ = fSystemPath;
893 fRootPath_ = fRootPath;
897 void XmlDocument::makeDirectoryBinaryTree(std::string fSystemPath,
898 std::string fRootPath,
900 xercesc::DOMElement* anchorNode)
903 struct dirent* entry;
905 std::string newFullPath =
"";
909 fSystemPath_ = fSystemPath;
910 fRootPath_ = fRootPath;
912 std::string fullPathName = fSystemPath_ +
918 if (!anchorNode) anchorNode = rootElement_;
920 if (!(dir = opendir(fullPathName.c_str())))
return;
922 while ((entry = readdir(dir)) != NULL)
924 std::string sName = std::string(entry->d_name);
926 if (sName.size() == 2) schar = sName.at(1);
927 if (((sName.size() == 1) && fchar ==
'.') ||
928 ((sName.size() == 2) && schar ==
'.'))
933 if (entry->d_type == DT_DIR)
935 fThisFolderPath_ = std::string(entry->d_name);
936 newFullPath = fSystemPath_ +
940 if (hierarchyPaths_.size() > 0) STDLINE(std::string(
"Before push_back: ") + hierarchyPaths_.back(), std::string(ACGreen) + std::string(ACReverse));
941 hierarchyPaths_.push_back(std::string(entry->d_name) + std::string(
""));
942 fFoldersPath_ += hierarchyPaths_.back() +
"/";
943 STDLINE(std::string(
"Before push_back: ") + hierarchyPaths_.back(), std::string(ACRed) + std::string(ACReverse));
944 xercesc::DOMElement* node = this->populateBinaryTreeNode(
946 std::string(entry->d_name),
950 this->makeDirectoryBinaryTree(fSystemPath, fRootPath, indent + 1, node);
951 STDLINE(std::string(
"Before popBack: ") + hierarchyPaths_.back(), std::string(ACGreen) + std::string(ACReverse));
952 if (hierarchyPaths_.size() > 0) hierarchyPaths_.pop_back();
953 if (hierarchyPaths_.size() > 0)
955 fFoldersPath_ = hierarchyPaths_.back() +
"/";
962 STDLINE(std::string(
"After popBack: ") + fFoldersPath_, std::string(ACRed) + std::string(ACReverse));
966 newFullPath = fSystemPath_ + std::string(
"/") + std::string(entry->d_name);
968 boost::regex re{
".*\\.root$" };
969 if (boost::regex_search(newFullPath, what, re))
971 fFileName_ = std::string(entry->d_name);
972 STDLINE(std::string(
"fFileName: ") + fFileName_, std::string(ACCyan) + std::string(ACReverse));
973 this->populateBinaryTreeNode(
986 xercesc::DOMElement* XmlDocument::populateBinaryTreeNode(xercesc::DOMElement* anchorNode,
991 std::string nm =
"unassigned";
992 xercesc::DOMElement* nodes = NULL;
1004 if (theNodes_.find(indent) != theNodes_.end())
1006 if (theNodes_.find(indent) != theNodes_.end()) nodes = theNodes_.find(indent)->second;
1007 if (theNames_.find(indent) != theNames_.end()) nm = theNames_.find(indent)->second;
1011 nodes = theDocument_->createElement(xercesc::XMLString::transcode(
"nodes"));
1012 theNodes_[indent] = nodes;
1013 theNames_[indent] = name;
1014 anchorNode->appendChild(nodes);
1018 xercesc::DOMElement* node = theDocument_->createElement(xercesc::XMLString::transcode(
"node"));
1019 nodes->appendChild(node);
1021 xercesc::DOMElement* nChilds = theDocument_->createElement(xercesc::XMLString::transcode(
"nChilds"));
1022 node->appendChild(nChilds);
1024 xercesc::DOMText* nChildsVal = theDocument_->createTextNode(xercesc::XMLString::transcode(
"x"));
1025 nChilds->appendChild(nChildsVal);
1027 xercesc::DOMElement* fSystemPathNode = theDocument_->createElement(xercesc::XMLString::transcode(
"fSystemPath"));
1028 node->appendChild(fSystemPathNode);
1030 xercesc::DOMText* fSystemPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fSystemPath_.c_str()));
1031 fSystemPathNode->appendChild(fSystemPathVal);
1033 xercesc::DOMElement* fRootPathNode = theDocument_->createElement(xercesc::XMLString::transcode(
"fRootPath"));
1034 node->appendChild(fRootPathNode);
1036 xercesc::DOMText* fRootPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fRootPath_.c_str()));
1037 fRootPathNode->appendChild(fRootPathVal);
1039 xercesc::DOMElement* fFoldersPathNode = theDocument_->createElement(xercesc::XMLString::transcode(
"fFoldersPath"));
1040 node->appendChild(fFoldersPathNode);
1042 xercesc::DOMText* foldersPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fFoldersPath_.c_str()));
1043 fFoldersPathNode->appendChild(foldersPathVal);
1045 xercesc::DOMElement* fThisFolderPath = NULL;
1046 xercesc::DOMElement* fFileOrHistName = NULL;
1047 xercesc::DOMText* fileOrDirNameVal = NULL;
1048 xercesc::DOMText* thisFolderNameVal = NULL;
1050 fThisFolderPath = theDocument_->createElement(xercesc::XMLString::transcode(
"fDisplayName"));
1054 fFileOrHistName = theDocument_->createElement(xercesc::XMLString::transcode(
"fFileName"));
1055 fileOrDirNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(name.c_str()));
1056 thisFolderNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(name.c_str()));
1057 ss_.str(
""); ss_ <<
"name: " << ACRed << fThisFolderPath_ << ACPlain <<
"/" << ACGreen << name;
1058 STDLINE(ss_.str(),
"");
1063 fFileOrHistName = theDocument_->createElement(xercesc::XMLString::transcode(
"fFileName"));
1064 fileOrDirNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(blank.c_str()));
1065 thisFolderNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fThisFolderPath_.c_str()));
1066 STDLINE(std::string(
"name : "), ACCyan);
1069 node->appendChild(fFileOrHistName);
1070 fFileOrHistName->appendChild(fileOrDirNameVal);
1072 node->appendChild(fThisFolderPath);
1073 fThisFolderPath->appendChild(thisFolderNameVal);
1075 xercesc::DOMElement* leaf = theDocument_->createElement(xercesc::XMLString::transcode(
"leaf"));
1076 node->appendChild(leaf);
1078 xercesc::DOMText* leafVal = theDocument_->createTextNode(xercesc::XMLString::transcode(isALeaf_[isLeaf].c_str()));
1079 leaf->appendChild(leafVal);
1084 void XmlDocument::setDarioStyle(
bool darioStyle)
1086 darioXMLStyle_ = darioStyle;