2 #include "otsdaq-core/XmlUtilities/XmlDocument.h"
3 #include "otsdaq-core/XmlUtilities/ConvertToXML.h"
4 #include "otsdaq-core/XmlUtilities/ConvertFromXML.h"
5 #include "otsdaq-core/MessageFacility/MessageFacility.h"
6 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
8 #include <xercesc/parsers/XercesDOMParser.hpp>
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/DOMImplementationRegistry.hpp>
16 #include <xercesc/dom/DOMImplementationLS.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/util/OutOfMemoryException.hpp>
29 #include <xercesc/framework/LocalFileFormatTarget.hpp>
35 #include <sys/types.h>
43 XmlDocument::XmlDocument(std::string rootName) :
44 rootTagName_(rootName)
46 INIT_MF(
"XmlDocument");
49 rootElement_ = theDocument_->getDocumentElement();
55 rootTagName_(doc.rootTagName_)
67 rootElement_ = theDocument_->getDocumentElement();
68 recursiveElementCopy(doc.rootElement_, rootElement_);
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(
92 CONVERT_TO_XML(
"http://www.w3.org/2001/XMLSchema-instance"),
93 CONVERT_TO_XML(rootTagName_),
96 catch (
const xercesc::OutOfMemoryException&)
98 XERCES_STD_QUALIFIER cerr <<
"OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
100 catch (
const xercesc::DOMException& e)
102 XERCES_STD_QUALIFIER cerr <<
"DOMException code is: " << e.code << XERCES_STD_QUALIFIER endl;
104 catch(
const xercesc::XMLException& e)
106 __COUT__ <<
"Error Message: " << XML_TO_CHAR(e.getMessage()) << std::endl;
110 XERCES_STD_QUALIFIER cerr <<
"An error occurred creating the theDocument_" << XERCES_STD_QUALIFIER endl;
114 XERCES_STD_QUALIFIER cerr <<
"Requested theImplementation_ is not supported" << XERCES_STD_QUALIFIER endl;
118 void XmlDocument::initPlatform(
void)
122 xercesc::XMLPlatformUtils::Initialize();
125 catch( xercesc::XMLException& e )
127 __COUT__ <<
"XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
133 void XmlDocument::terminatePlatform(
void)
138 theDocument_->release();
143 XERCES_STD_QUALIFIER cerr <<
"An error occurred destroying the theDocument_" << XERCES_STD_QUALIFIER endl;
148 xercesc::XMLPlatformUtils::Terminate();
150 catch( xercesc::XMLException& e )
152 __COUT__ <<
"XML toolkit teardown error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
161 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName, std::string childText, xercesc::DOMElement* parent)
163 if(parent == 0)
return 0;
164 xercesc::DOMElement* child;
167 child = theDocument_->createElement(CONVERT_TO_XML(childName));
169 catch (xercesc::DOMException& e)
171 __COUT__ <<
"Can't use the name: " << childName <<
" to create the child element because the exception says: "
172 << XML_TO_CHAR(e.getMessage()) <<
". Very likely you have a name that starts with a number and that's not allowed!" << std::endl;
174 parent->appendChild(child);
178 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(childText)));
182 __COUT_ERR__ <<
"Error caught attempting to create a text node for this text: " <<
183 childText <<
". Converting instead to 'Illegal text..'" << std::endl;
184 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(
"Illegal text content blocked.")));
194 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName, std::string childText, std::string parentName,
unsigned int parentIndex)
196 xercesc::DOMNodeList* nodeList = theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName));
198 if(parentIndex >= nodeList->getLength())
200 __COUT__ <<
"WARNING: Illegal parent index attempted in tags with name: " << parentName <<
", index: " << parentIndex << std::endl;
204 return addTextElementToParent(childName, childText,(xercesc::DOMElement*)(nodeList->item(parentIndex)));
208 void XmlDocument::copyDocument(
const xercesc::DOMDocument* toCopy, xercesc::DOMDocument* copy)
210 recursiveElementCopy(toCopy->getDocumentElement(),copy->getDocumentElement());
214 void XmlDocument::recursiveElementCopy(
const xercesc::DOMElement* toCopy, xercesc::DOMElement* copy)
216 xercesc::DOMNodeList* nodeListToCopy = toCopy->getChildNodes();
217 xercesc::DOMNode* iNode;
218 xercesc::DOMDocument* copyDocument = copy->getOwnerDocument();
219 for(
unsigned int i=0; i<nodeListToCopy->getLength(); i++)
221 iNode = nodeListToCopy->item(i);
222 xercesc::DOMElement* child = copyDocument->createElement(iNode->getNodeName());
223 copy->appendChild(child);
224 if( iNode->getFirstChild() != 0 && iNode->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)
226 child->appendChild(copyDocument->createTextNode(child->getFirstChild()->getNodeValue()));
228 recursiveElementCopy((xercesc::DOMElement*)(iNode),child);
394 void XmlDocument::outputXmlDocument (std::ostringstream *out,
bool dispStdOut)
396 recursiveOutputXmlDocument(theDocument_->getDocumentElement(),out,dispStdOut);
402 void XmlDocument::recursiveOutputXmlDocument (xercesc::DOMElement *currEl, std::ostringstream *out,
bool dispStdOut, std::string tabStr)
405 if(dispStdOut) std::cout << __COUT_HDR_FL__<< tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName()) ;
406 if(out) *out << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
409 if( currEl->getFirstChild() != NULL &&
410 currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)
412 if(dispStdOut) std::cout <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
413 if(out) *out <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
416 xercesc::DOMNodeList *nodeList = currEl->getChildNodes();
419 if(dispStdOut) std::cout << ((nodeList->getLength() == 0 ||
420 (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))?
"/":
"")
421 <<
">" <<
" len:" << nodeList->getLength() << std::endl;
422 if(out) *out << ((nodeList->getLength() == 0 ||
423 (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))?
"/":
"")
427 std::string newTabStr = tabStr +
"\t";
428 for(
unsigned int i = 0; i<nodeList->getLength();++i)
429 if(nodeList->item(i)->getNodeType() != xercesc::DOMNode::TEXT_NODE)
430 recursiveOutputXmlDocument ((xercesc::DOMElement*)(nodeList->item(i)),out,dispStdOut,newTabStr);
433 if(nodeList->getLength() > 1 || (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE))
435 if(dispStdOut) std::cout << __COUT_HDR_FL__<< tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">" << std::endl;
436 if(out) *out << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">" << std::endl;
518 std::string XmlDocument::escapeString(std::string inString,
bool allowWhiteSpace)
522 unsigned int ws = -1;
525 for(
unsigned int i=0; i<inString.length(); i++)
526 if(inString[i] !=
' ')
528 if(doit) std::cout << __COUT_HDR_FL__<< inString[i] <<
":" <<
529 (int)inString[i] <<
":" << inString << std::endl;
532 if(inString[i] ==
'\r' || inString[i] ==
'\n' ||
533 inString[i] ==
'\t' ||
535 (inString[i] >
char(126) && inString[i] < char(161)))
543 sprintf(htmlTmp,
"&#%3.3d",inString[i]);
544 inString.insert(i,htmlTmp);
545 inString.replace(i+5,1,1,
';');
560 sprintf(htmlTmp,
"        ");
561 inString.insert(i,htmlTmp);
562 inString.replace(i+47,1,1,
';');
569 sprintf(htmlTmp,
"	");
570 inString.insert(i,htmlTmp);
571 inString.replace(i+5,1,1,
';');
584 if(doit) std::cout << __COUT_HDR_FL__<< inString << std::endl;
588 if(doit) std::cout << __COUT_HDR_FL__<< inString << std::endl;
591 if(inString[i] ==
'\"' || inString[i] ==
'\'')
593 inString.insert(i,(inString[i] ==
'\'')?
"&apos":
""");
594 inString.replace(i+5,1,1,
';');
598 else if(inString[i] ==
'&')
600 inString.insert(i,
"&");
601 inString.replace(i+4,1,1,
';');
604 else if(inString[i] ==
'<' || inString[i] ==
'>')
606 inString.insert(i,(inString[i] ==
'<')?
"<":
">");
607 inString.replace(i+3,1,1,
';');
610 else if(inString[i] >=
char(161) && inString[i] <=
char(255))
612 sprintf(htmlTmp,
"&#%3.3d",inString[i]);
613 inString.insert(i,htmlTmp);
614 inString.replace(i+5,1,1,
';');
618 if(doit) std::cout << __COUT_HDR_FL__<< inString << std::endl;
622 else if(allowWhiteSpace)
624 if(i-1 == ws)
continue;
629 inString.insert(i,
" ");
632 inString.insert(i,
" ");
633 inString.replace(i+5,1,1,
';');
638 if(doit) std::cout << __COUT_HDR_FL__<< inString.size() <<
" " << ws << std::endl;
640 inString.substr(0,ws+1);
642 if(doit) std::cout << __COUT_HDR_FL__<< inString.size() <<
" " << inString << std::endl;
644 if(ws == (
unsigned int)-1)
return "";
645 return inString.substr(0,ws+1);
652 void XmlDocument::recursiveRemoveChild(xercesc::DOMElement *childEl, xercesc::DOMElement *parentEl)
655 xercesc::DOMNodeList* nodeList = childEl->getChildNodes();
656 for(
unsigned int i = 0; i<nodeList->getLength(); ++i)
657 recursiveRemoveChild((xercesc::DOMElement*)(nodeList->item(nodeList->getLength()-1-i)),childEl);
660 parentEl->removeChild(childEl);
668 void XmlDocument::saveXmlDocument (std::string filePath)
670 std::cout << __COUT_HDR_FL__<<
"Saving theDocument_ to file: " << filePath << std::endl;
673 xercesc::DOMImplementation *saveImplementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"LS"));
675 std::cout << __COUT_HDR_FL__<<
"XERCES Version: " << _XERCES_VERSION << std::endl;
677 #if _XERCES_VERSION >= 30000
681 xercesc::DOMLSSerializer *serializer = ((xercesc::DOMImplementationLS*)saveImplementation)->createLSSerializer();
684 if (serializer->getDomConfig()->canSetParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true))
685 serializer->getDomConfig()->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
688 serializer->setNewLine(CONVERT_TO_XML(
"\r\n"));
694 xercesc::XMLFormatTarget* formatTarget;
698 formatTarget =
new xercesc::LocalFileFormatTarget(filePath.c_str());
702 std::cout << __COUT_HDR_FL__<<
"Inaccessible file path: " << filePath << std::endl;
703 serializer->release();
710 xercesc::DOMLSOutput *output = ((xercesc::DOMImplementationLS*)saveImplementation)->createLSOutput();
713 output->setByteStream(formatTarget);
715 serializer->write(theDocument_, output);
716 serializer->release();
721 xercesc::DOMWriter *serializer = ((xercesc::DOMImplementationLS*)saveImplementation)->createDOMWriter();
722 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
733 XMLCh *tempFilePath = xercesc::XMLString::transcode(filePath.c_str());
734 xercesc::XMLFormatTarget* formatTarget;
737 formatTarget =
new xercesc::LocalFileFormatTarget(tempFilePath);
741 std::cout << __COUT_HDR_FL__<<
"Inaccessible file path: " << filePath << std::endl;
742 serializer->release();
743 xercesc::XMLString::release(&tempFilePath);
749 serializer->writeNode(formatTarget, *theDocument_);
750 serializer->release();
751 xercesc::XMLString::release(&tempFilePath);
759 #if _XERCES_VERSION >= 30000
770 bool XmlDocument::loadXmlDocument (std::string filePath)
772 std::cout << __COUT_HDR_FL__<<
"Loading theDocument_ from file: " << filePath << std::endl;
774 struct stat fileStatus;
776 if(stat(filePath.c_str(), &fileStatus) != 0)
778 std::cout << __COUT_HDR_FL__<<
"File not accessible." << std::endl;
786 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
788 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
789 parser->setDoNamespaces (
true );
790 parser->setDoSchema (
true );
791 parser->useCachedGrammarInParse (
false );
795 parser->parse( filePath.c_str() );
798 theDocument_ = parser->adoptDocument();
801 rootElement_ = theDocument_->getDocumentElement();
803 throw(std::runtime_error(
"empty XML theDocument_" ));
806 catch( xercesc::XMLException& e )
808 std::cout << __COUT_HDR_FL__<<
"Error parsing file." << std::endl;