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>
51 rootElement_ = theDocument_->getDocumentElement();
66 __COUT__ <<
"in" << std::endl;
68 rootElement_ = theDocument_->getDocumentElement();
69 recursiveElementCopy(doc.rootElement_, rootElement_);
70 __COUT__ <<
"out" << std::endl;
75 XmlDocument::~XmlDocument(
void)
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)
165 theDocument_->release();
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())
191 const std::string& childText,
192 xercesc::DOMElement* parent)
196 __SS__ <<
"Illegal Null Parent Pointer!" << __E__;
200 xercesc::DOMElement* child =
nullptr;
203 child = theDocument_->createElement(CONVERT_TO_XML(childName));
205 catch(xercesc::DOMException& e)
207 __COUT__ <<
"Can't use the name: " << childName
208 <<
" to create the child element because the exception says: "
209 << XML_TO_CHAR(e.getMessage())
210 <<
". Very likely you have a name that starts with a number and that's "
214 parent->appendChild(child);
218 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(childText)));
223 __COUT_ERR__ <<
"Error caught attempting to create a text node for this text: "
224 << childText <<
". Converting instead to 'Illegal text..'"
226 child->appendChild(theDocument_->createTextNode(
227 CONVERT_TO_XML(
"Illegal text content blocked.")));
238 const std::string& childText,
239 const std::string& parentName,
240 unsigned int parentIndex)
242 xercesc::DOMNodeList* nodeList =
243 theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName));
245 if(parentIndex >= nodeList->getLength())
247 __COUT__ <<
"WARNING: Illegal parent index attempted in tags with name: "
248 << parentName <<
", index: " << parentIndex << std::endl;
253 childName, childText, (xercesc::DOMElement*)(nodeList->item(parentIndex)));
258 xercesc::DOMDocument* copy)
260 recursiveElementCopy(toCopy->getDocumentElement(), copy->getDocumentElement());
264 void XmlDocument::recursiveElementCopy(
const xercesc::DOMElement* toCopy,
265 xercesc::DOMElement* copy)
267 xercesc::DOMNodeList* nodeListToCopy =
268 toCopy->getChildNodes();
269 xercesc::DOMNode* iNode;
270 xercesc::DOMDocument*
copyDocument = copy->getOwnerDocument();
271 for(
unsigned int i = 0; i < nodeListToCopy->getLength(); i++)
273 iNode = nodeListToCopy->item(i);
274 xercesc::DOMElement* child =
copyDocument->createElement(iNode->getNodeName());
275 copy->appendChild(child);
276 if(child->getFirstChild() != NULL)
278 if(iNode->getFirstChild() != 0 &&
279 iNode->getFirstChild()->getNodeType() ==
280 xercesc::DOMNode::TEXT_NODE)
284 copyDocument->createTextNode(child->getFirstChild()->getNodeValue()));
286 recursiveElementCopy((xercesc::DOMElement*)(iNode), child);
477 void XmlDocument::setDocument(xercesc::DOMDocument* doc) { theDocument_ = doc; }
482 std::ostringstream* out,
484 const std::string& tabStr)
489 __COUT__ << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
493 *out << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
497 if(currEl->getFirstChild() != NULL &&
498 currEl->getFirstChild()->getNodeType() ==
499 xercesc::DOMNode::TEXT_NODE)
503 std::cout <<
" value='"
504 << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
506 *out <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()))
510 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
514 std::cout << ((nodeList->getLength() == 0 ||
515 (nodeList->getLength() == 1 &&
516 currEl->getFirstChild()->getNodeType() ==
517 xercesc::DOMNode::TEXT_NODE))
522 *out << ((nodeList->getLength() == 0 ||
523 (nodeList->getLength() == 1 &&
524 currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))
530 std::string newTabStr = tabStr +
"\t";
531 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
532 if(nodeList->item(i)->getNodeType() !=
533 xercesc::DOMNode::TEXT_NODE)
535 (xercesc::DOMElement*)(nodeList->item(i)), out, dispStdOut, newTabStr);
538 if(nodeList->getLength() > 1 ||
539 (nodeList->getLength() == 1 &&
540 currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE))
543 __COUT__ << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
546 *out << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
633 xercesc::DOMElement* parentEl)
636 xercesc::DOMNodeList* nodeList =
637 childEl->getChildNodes();
638 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
640 (xercesc::DOMElement*)(nodeList->item(nodeList->getLength() - 1 - i)),
644 parentEl->removeChild(childEl);
654 __COUT__ <<
"Saving theDocument_ to file: " << filePath << std::endl;
659 xercesc::DOMImplementation* saveImplementation =
660 xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"LS"));
664 #if _XERCES_VERSION >= 30000
669 xercesc::DOMLSSerializer* serializer =
670 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSSerializer();
673 if(serializer->getDomConfig()->canSetParameter(
674 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true))
675 serializer->getDomConfig()->setParameter(
676 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
679 serializer->setNewLine(CONVERT_TO_XML(
"\r\n"));
685 xercesc::XMLFormatTarget* formatTarget;
689 formatTarget =
new xercesc::LocalFileFormatTarget(filePath.c_str());
693 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
694 serializer->release();
701 xercesc::DOMLSOutput* output =
702 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSOutput();
705 output->setByteStream(formatTarget);
707 serializer->write(theDocument_, output);
708 serializer->release();
713 xercesc::DOMWriter* serializer =
714 ((xercesc::DOMImplementationLS*)saveImplementation)->createDOMWriter();
715 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
726 XMLCh* tempFilePath = xercesc::XMLString::transcode(filePath.c_str());
727 xercesc::XMLFormatTarget* formatTarget;
730 formatTarget =
new xercesc::LocalFileFormatTarget(tempFilePath);
734 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
735 serializer->release();
736 xercesc::XMLString::release(&tempFilePath);
742 serializer->writeNode(formatTarget, *theDocument_);
743 serializer->release();
744 xercesc::XMLString::release(&tempFilePath);
751 #if _XERCES_VERSION >= 30000
761 bool XmlDocument::loadXmlDocument(
const std::string& filePath)
763 __COUT__ <<
"Loading theDocument_ from file: " << filePath << std::endl;
765 struct stat fileStatus;
767 if(stat(filePath.c_str(), &fileStatus) != 0)
769 __COUT__ <<
"File not accessible." << std::endl;
776 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
777 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
778 parser->setDoNamespaces(
true);
779 parser->setDoSchema(
true);
780 parser->useCachedGrammarInParse(
false);
784 parser->parse(filePath.c_str());
787 theDocument_ = parser->adoptDocument();
792 rootElement_ = theDocument_->getDocumentElement();
794 throw(std::runtime_error(
"empty XML theDocument_"));
796 catch(xercesc::XMLException& e)
798 __COUT__ <<
"Error parsing file." << std::endl;
807 void XmlDocument::setAnchors(
const std::string& fSystemPath,
808 const std::string& fRootPath)
810 fSystemPath_ = fSystemPath;
811 fRootPath_ = fRootPath;
815 void XmlDocument::makeDirectoryBinaryTree(
const std::string& fSystemPath,
816 const std::string& fRootPath,
818 xercesc::DOMElement* anchorNode)
821 struct dirent* entry;
823 std::string newFullPath =
"";
827 fSystemPath_ = fSystemPath;
828 fRootPath_ = fRootPath;
830 std::string fullPathName = fSystemPath_ +
836 if (!anchorNode) anchorNode = rootElement_;
838 if (!(dir = opendir(fullPathName.c_str())))
return;
840 while ((entry = readdir(dir)) != NULL)
842 std::string sName = std::string(entry->d_name);
844 if ( sName.size() == 2) schar = sName.at(1);
845 if (((sName.size() == 1) && fchar ==
'.') ||
846 ((sName.size() == 2) && schar ==
'.'))
851 if (entry->d_type == DT_DIR)
853 fThisFolderPath_ = std::string(entry->d_name);
854 newFullPath = fSystemPath_ +
858 hierarchyPaths_.push_back(std::string(entry->d_name) + std::string(
""));
859 fFoldersPath_ += hierarchyPaths_.back() +
"/";
860 xercesc::DOMElement* node = this->populateBinaryTreeNode(
862 std::string(entry->d_name),
866 this->makeDirectoryBinaryTree(fSystemPath, fRootPath, indent + 1, node);
867 if (hierarchyPaths_.size() > 0) hierarchyPaths_.pop_back();
868 if (hierarchyPaths_.size() > 0)
870 fFoldersPath_ = hierarchyPaths_.back() +
"/";
880 newFullPath = fSystemPath_ + std::string(
"/") + std::string(entry->d_name);
882 boost::regex re{
".*\\.root$" };
883 if (boost::regex_search(newFullPath, what, re))
885 fFileName_ = std::string(entry->d_name);
887 for(
unsigned int i=0; i<hierarchyPaths_.size(); ++i)
889 fFoldersPath_ += hierarchyPaths_[i] + std::string(
"/") ;
891 this->populateBinaryTreeNode(
904 xercesc::DOMElement* XmlDocument::populateBinaryTreeNode(xercesc::DOMElement* anchorNode,
905 const std::string& name,
909 std::string nm =
"unassigned";
910 xercesc::DOMElement* nodes = NULL;
922 if (theNodes_.find(indent) != theNodes_.end())
924 if (theNodes_.find(indent) != theNodes_.end()) nodes = theNodes_.find(indent)->second;
925 if (theNames_.find(indent) != theNames_.end()) nm = theNames_.find(indent)->second;
929 nodes = theDocument_->createElement(xercesc::XMLString::transcode(
"nodes"));
930 theNodes_[indent] = nodes;
931 theNames_[indent] = name;
932 anchorNode->appendChild(nodes);
935 xercesc::DOMElement* node = theDocument_->createElement(xercesc::XMLString::transcode(
"node"));
936 nodes->appendChild(node);
938 xercesc::DOMElement* nChilds = theDocument_->createElement(xercesc::XMLString::transcode(
"nChilds"));
939 node->appendChild(nChilds);
941 xercesc::DOMText* nChildsVal = theDocument_->createTextNode(xercesc::XMLString::transcode(
"x"));
942 nChilds->appendChild(nChildsVal);
944 xercesc::DOMElement* fSystemPathNode = theDocument_->createElement(xercesc::XMLString::transcode(
"fSystemPath"));
945 node->appendChild(fSystemPathNode);
947 xercesc::DOMText* fSystemPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fSystemPath_.c_str()));
948 fSystemPathNode->appendChild(fSystemPathVal);
950 xercesc::DOMElement* fRootPathNode = theDocument_->createElement(xercesc::XMLString::transcode(
"fRootPath"));
951 node->appendChild(fRootPathNode);
953 xercesc::DOMText* fRootPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fRootPath_.c_str()));
954 fRootPathNode->appendChild(fRootPathVal);
956 xercesc::DOMElement* fFoldersPathNode = theDocument_->createElement(xercesc::XMLString::transcode(
"fFoldersPath"));
957 node->appendChild(fFoldersPathNode);
959 xercesc::DOMText* foldersPathVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fFoldersPath_.c_str()));
960 fFoldersPathNode->appendChild(foldersPathVal);
962 xercesc::DOMElement* fThisFolderPath = NULL;
963 xercesc::DOMElement* fFileOrHistName = NULL;
964 xercesc::DOMText* fileOrDirNameVal = NULL;
965 xercesc::DOMText* thisFolderNameVal = NULL;
967 fThisFolderPath = theDocument_->createElement(xercesc::XMLString::transcode(
"fDisplayName"));
971 fFileOrHistName = theDocument_->createElement(xercesc::XMLString::transcode(
"fFileName"));
972 fileOrDirNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(name.c_str()));
973 thisFolderNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(name.c_str()));
974 ss_.str(
""); ss_ <<
"name: " << ACRed << name << ACPlain <<
"/" << ACGreen << name;
975 STDLINE(ss_.str(),
"");
980 fFileOrHistName = theDocument_->createElement(xercesc::XMLString::transcode(
"fFileName"));
981 fileOrDirNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(blank.c_str()));
982 thisFolderNameVal = theDocument_->createTextNode(xercesc::XMLString::transcode(fThisFolderPath_.c_str()));
983 ss_.str(
""); ss_ <<
"name: " << ACRed << fThisFolderPath_ << ACPlain <<
"/" << ACGreen << name;
984 STDLINE(ss_.str(),
"");
987 node->appendChild(fFileOrHistName);
988 fFileOrHistName->appendChild(fileOrDirNameVal);
990 node->appendChild(fThisFolderPath);
991 fThisFolderPath->appendChild(thisFolderNameVal);
993 xercesc::DOMElement* leaf = theDocument_->createElement(xercesc::XMLString::transcode(
"leaf"));
994 node->appendChild(leaf);
996 xercesc::DOMText* leafVal = theDocument_->createTextNode(xercesc::XMLString::transcode(isALeaf_[isLeaf].c_str()));
997 leaf->appendChild(leafVal);
1002 void XmlDocument::setDarioStyle(
bool darioStyle)
1004 darioXMLStyle_ = darioStyle;
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)
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 stackTrace(void)