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 __MOUT__ <<
"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 __MOUT__ <<
"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 __MOUT__ <<
"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 __MOUT__ <<
"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);
175 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(childText)));
184 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName, std::string childText, std::string parentName,
unsigned int parentIndex)
186 xercesc::DOMNodeList* nodeList = theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName));
188 if(parentIndex >= nodeList->getLength())
190 __MOUT__ <<
"WARNING: Illegal parent index attempted in tags with name: " << parentName <<
", index: " << parentIndex << std::endl;
194 return addTextElementToParent(childName, childText,(xercesc::DOMElement*)(nodeList->item(parentIndex)));
198 void XmlDocument::copyDocument(
const xercesc::DOMDocument* toCopy, xercesc::DOMDocument* copy)
200 recursiveElementCopy(toCopy->getDocumentElement(),copy->getDocumentElement());
204 void XmlDocument::recursiveElementCopy(
const xercesc::DOMElement* toCopy, xercesc::DOMElement* copy)
206 xercesc::DOMNodeList* nodeListToCopy = toCopy->getChildNodes();
207 xercesc::DOMNode* iNode;
208 xercesc::DOMDocument* copyDocument = copy->getOwnerDocument();
209 for(
unsigned int i=0; i<nodeListToCopy->getLength(); i++)
211 iNode = nodeListToCopy->item(i);
212 xercesc::DOMElement* child = copyDocument->createElement(iNode->getNodeName());
213 copy->appendChild(child);
214 if( iNode->getFirstChild() != 0 && iNode->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)
216 child->appendChild(copyDocument->createTextNode(child->getFirstChild()->getNodeValue()));
218 recursiveElementCopy((xercesc::DOMElement*)(iNode),child);
384 void XmlDocument::outputXmlDocument (std::ostringstream *out,
bool dispStdOut)
386 recursiveOutputXmlDocument(theDocument_->getDocumentElement(),out,dispStdOut);
392 void XmlDocument::recursiveOutputXmlDocument (xercesc::DOMElement *currEl, std::ostringstream *out,
bool dispStdOut, std::string tabStr)
395 if(dispStdOut) std::cout << __COUT_HDR_FL__<< tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName()) ;
396 if(out) *out << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
399 if( currEl->getFirstChild() != NULL &&
400 currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE)
402 if(dispStdOut) std::cout <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
403 if(out) *out <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
406 xercesc::DOMNodeList *nodeList = currEl->getChildNodes();
409 if(dispStdOut) std::cout << ((nodeList->getLength() == 0 ||
410 (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))?
"/":
"")
411 <<
">" <<
" len:" << nodeList->getLength() << std::endl;
412 if(out) *out << ((nodeList->getLength() == 0 ||
413 (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))?
"/":
"")
417 std::string newTabStr = tabStr +
"\t";
418 for(
unsigned int i = 0; i<nodeList->getLength();++i)
419 if(nodeList->item(i)->getNodeType() != xercesc::DOMNode::TEXT_NODE)
420 recursiveOutputXmlDocument ((xercesc::DOMElement*)(nodeList->item(i)),out,dispStdOut,newTabStr);
423 if(nodeList->getLength() > 1 || (nodeList->getLength() == 1 && currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE))
425 if(dispStdOut) std::cout << __COUT_HDR_FL__<< tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">" << std::endl;
426 if(out) *out << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">" << std::endl;
508 std::string XmlDocument::escapeString(std::string inString,
bool allowWhiteSpace)
512 unsigned int ws = -1;
515 for(
unsigned int i=0; i<inString.length(); i++)
516 if(inString[i] !=
' ')
520 if(doit) std::cout << __COUT_HDR_FL__<< inString[i] <<
":" <<
521 (int)inString[i] <<
":" << inString << std::endl;
524 if(inString[i] ==
'\r' || inString[i] ==
'\n' ||
525 inString[i] ==
'\t' ||
527 (inString[i] >
char(126) && inString[i] < char(161)))
530 if(allowWhiteSpace &&
533 sprintf(htmlTmp,
"&#%3.3d",inString[i]);
534 inString.insert(i,htmlTmp);
535 inString.replace(i+5,1,1,
';');
539 else if(allowWhiteSpace &&
545 sprintf(htmlTmp,
"        ");
546 inString.insert(i,htmlTmp);
547 inString.replace(i+47,1,1,
';');
554 sprintf(htmlTmp,
"	");
555 inString.insert(i,htmlTmp);
556 inString.replace(i+5,1,1,
';');
566 if(doit) std::cout << __COUT_HDR_FL__<< inString << std::endl;
570 if(doit) std::cout << __COUT_HDR_FL__<< inString << std::endl;
573 if(inString[i] ==
'\"' || inString[i] ==
'\'')
575 inString.insert(i,(inString[i] ==
'\'')?
"&apos":
""");
576 inString.replace(i+5,1,1,
';');
580 else if(inString[i] ==
'&')
582 inString.insert(i,
"&");
583 inString.replace(i+4,1,1,
';');
586 else if(inString[i] ==
'<' || inString[i] ==
'>')
588 inString.insert(i,(inString[i] ==
'<')?
"<":
">");
589 inString.replace(i+3,1,1,
';');
592 else if(inString[i] >=
char(161) && inString[i] <=
char(255))
594 sprintf(htmlTmp,
"&#%3.3d",inString[i]);
595 inString.insert(i,htmlTmp);
596 inString.replace(i+5,1,1,
';');
600 if(doit) std::cout << __COUT_HDR_FL__<< inString << std::endl;
604 else if(allowWhiteSpace)
606 if(i-1 == ws)
continue;
611 inString.insert(i,
" ");
614 inString.insert(i,
" ");
615 inString.replace(i+5,1,1,
';');
620 if(doit) std::cout << __COUT_HDR_FL__<< inString.size() <<
" " << ws << std::endl;
622 inString.substr(0,ws+1);
624 if(doit) std::cout << __COUT_HDR_FL__<< inString.size() <<
" " << inString << std::endl;
626 if(ws == (
unsigned int)-1)
return "";
627 return inString.substr(0,ws+1);
634 void XmlDocument::recursiveRemoveChild(xercesc::DOMElement *childEl, xercesc::DOMElement *parentEl)
637 xercesc::DOMNodeList* nodeList = childEl->getChildNodes();
638 for(
unsigned int i = 0; i<nodeList->getLength(); ++i)
639 recursiveRemoveChild((xercesc::DOMElement*)(nodeList->item(nodeList->getLength()-1-i)),childEl);
642 parentEl->removeChild(childEl);
650 void XmlDocument::saveXmlDocument (std::string filePath)
652 std::cout << __COUT_HDR_FL__<<
"Saving theDocument_ to file: " << filePath << std::endl;
655 xercesc::DOMImplementation *saveImplementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"LS"));
657 std::cout << __COUT_HDR_FL__<<
"XERCES Version: " << _XERCES_VERSION << std::endl;
659 #if _XERCES_VERSION >= 30000
663 xercesc::DOMLSSerializer *serializer = ((xercesc::DOMImplementationLS*)saveImplementation)->createLSSerializer();
666 if (serializer->getDomConfig()->canSetParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true))
667 serializer->getDomConfig()->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
670 serializer->setNewLine(CONVERT_TO_XML(
"\r\n"));
676 xercesc::XMLFormatTarget* formatTarget;
680 formatTarget =
new xercesc::LocalFileFormatTarget(filePath.c_str());
684 std::cout << __COUT_HDR_FL__<<
"Inaccessible file path: " << filePath << std::endl;
685 serializer->release();
692 xercesc::DOMLSOutput *output = ((xercesc::DOMImplementationLS*)saveImplementation)->createLSOutput();
695 output->setByteStream(formatTarget);
697 serializer->write(theDocument_, output);
698 serializer->release();
703 xercesc::DOMWriter *serializer = ((xercesc::DOMImplementationLS*)saveImplementation)->createDOMWriter();
704 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
715 XMLCh *tempFilePath = xercesc::XMLString::transcode(filePath.c_str());
716 xercesc::XMLFormatTarget* formatTarget;
719 formatTarget =
new xercesc::LocalFileFormatTarget(tempFilePath);
723 std::cout << __COUT_HDR_FL__<<
"Inaccessible file path: " << filePath << std::endl;
724 serializer->release();
725 xercesc::XMLString::release(&tempFilePath);
731 serializer->writeNode(formatTarget, *theDocument_);
732 serializer->release();
733 xercesc::XMLString::release(&tempFilePath);
741 #if _XERCES_VERSION >= 30000
752 bool XmlDocument::loadXmlDocument (std::string filePath)
754 std::cout << __COUT_HDR_FL__<<
"Loading theDocument_ from file: " << filePath << std::endl;
756 struct stat fileStatus;
758 if(stat(filePath.c_str(), &fileStatus) != 0)
760 std::cout << __COUT_HDR_FL__<<
"File not accessible." << std::endl;
768 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
770 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
771 parser->setDoNamespaces (
true );
772 parser->setDoSchema (
true );
773 parser->useCachedGrammarInParse (
false );
777 parser->parse( filePath.c_str() );
780 theDocument_ = parser->adoptDocument();
783 rootElement_ = theDocument_->getDocumentElement();
785 throw(std::runtime_error(
"empty XML theDocument_" ));
788 catch( xercesc::XMLException& e )
790 std::cout << __COUT_HDR_FL__<<
"Error parsing file." << std::endl;