2 #include "otsdaq-core/XmlUtilities/XmlDocument.h"
3 #include "otsdaq-core/Macros/CoutMacros.h"
4 #include "otsdaq-core/MessageFacility/MessageFacility.h"
5 #include "otsdaq-core/XmlUtilities/ConvertFromXML.h"
6 #include "otsdaq-core/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>
37 #include <sys/types.h>
43 XmlDocument::XmlDocument(std::string rootName) : rootTagName_(rootName)
48 rootElement_ = theDocument_->getDocumentElement();
53 XmlDocument::XmlDocument(
const XmlDocument& doc) : rootTagName_(doc.rootTagName_)
65 rootElement_ = theDocument_->getDocumentElement();
66 recursiveElementCopy(doc.rootElement_, rootElement_);
72 XmlDocument::~XmlDocument(
void)
79 void XmlDocument::initDocument(
void)
84 xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"Core"));
86 if(theImplementation_)
90 theDocument_ = theImplementation_->createDocument(
91 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"
101 << XERCES_STD_QUALIFIER endl;
103 catch(
const xercesc::DOMException& e)
105 XERCES_STD_QUALIFIER cerr <<
"DOMException code is: " << e.code
106 << XERCES_STD_QUALIFIER endl;
108 catch(
const xercesc::XMLException& e)
110 __COUT__ <<
"Error Message: " << XML_TO_CHAR(e.getMessage()) << std::endl;
114 XERCES_STD_QUALIFIER cerr <<
"An error occurred creating the theDocument_"
115 << XERCES_STD_QUALIFIER endl;
119 XERCES_STD_QUALIFIER cerr <<
"Requested theImplementation_ is not supported"
120 << XERCES_STD_QUALIFIER endl;
124 void XmlDocument::initPlatform(
void)
128 xercesc::XMLPlatformUtils::Initialize();
132 catch(xercesc::XMLException& e)
134 __COUT__ <<
"XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage())
140 void XmlDocument::terminatePlatform(
void)
145 theDocument_->release();
150 XERCES_STD_QUALIFIER cerr <<
"An error occurred destroying the theDocument_"
151 << XERCES_STD_QUALIFIER endl;
156 xercesc::XMLPlatformUtils::Terminate();
158 catch(xercesc::XMLException& e)
160 __COUT__ <<
"XML toolkit teardown error: " << XML_TO_CHAR(e.getMessage())
170 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName,
171 std::string childText,
172 xercesc::DOMElement* parent)
176 __SS__ <<
"Illegal Null Parent Pointer!" << __E__;
180 xercesc::DOMElement* child;
183 child = theDocument_->createElement(CONVERT_TO_XML(childName));
185 catch(xercesc::DOMException& e)
187 __COUT__ <<
"Can't use the name: " << childName
188 <<
" to create the child element because the exception says: "
189 << XML_TO_CHAR(e.getMessage())
190 <<
". Very likely you have a name that starts with a number and that's "
194 parent->appendChild(child);
198 child->appendChild(theDocument_->createTextNode(CONVERT_TO_XML(childText)));
202 __COUT_ERR__ <<
"Error caught attempting to create a text node for this text: "
203 << childText <<
". Converting instead to 'Illegal text..'"
205 child->appendChild(theDocument_->createTextNode(
206 CONVERT_TO_XML(
"Illegal text content blocked.")));
216 xercesc::DOMElement* XmlDocument::addTextElementToParent(std::string childName,
217 std::string childText,
218 std::string parentName,
219 unsigned int parentIndex)
221 xercesc::DOMNodeList* nodeList =
222 theDocument_->getElementsByTagName(CONVERT_TO_XML(parentName));
224 if(parentIndex >= nodeList->getLength())
226 __COUT__ <<
"WARNING: Illegal parent index attempted in tags with name: "
227 << parentName <<
", index: " << parentIndex << std::endl;
231 return addTextElementToParent(
232 childName, childText, (xercesc::DOMElement*)(nodeList->item(parentIndex)));
236 void XmlDocument::copyDocument(
const xercesc::DOMDocument* toCopy,
237 xercesc::DOMDocument* copy)
239 recursiveElementCopy(toCopy->getDocumentElement(), copy->getDocumentElement());
243 void XmlDocument::recursiveElementCopy(
const xercesc::DOMElement* toCopy,
244 xercesc::DOMElement* copy)
246 xercesc::DOMNodeList* nodeListToCopy =
247 toCopy->getChildNodes();
248 xercesc::DOMNode* iNode;
249 xercesc::DOMDocument* copyDocument = copy->getOwnerDocument();
250 for(
unsigned int i = 0; i < nodeListToCopy->getLength(); i++)
252 iNode = nodeListToCopy->item(i);
253 xercesc::DOMElement* child = copyDocument->createElement(iNode->getNodeName());
254 copy->appendChild(child);
255 if(iNode->getFirstChild() != 0 &&
256 iNode->getFirstChild()->getNodeType() ==
257 xercesc::DOMNode::TEXT_NODE)
261 copyDocument->createTextNode(child->getFirstChild()->getNodeValue()));
263 recursiveElementCopy((xercesc::DOMElement*)(iNode), child);
447 void XmlDocument::outputXmlDocument(std::ostringstream* out,
bool dispStdOut)
449 recursiveOutputXmlDocument(theDocument_->getDocumentElement(), out, dispStdOut);
455 void XmlDocument::recursiveOutputXmlDocument(xercesc::DOMElement* currEl,
456 std::ostringstream* out,
462 __COUT__ << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
464 *out << tabStr <<
"<" << XML_TO_CHAR(currEl->getNodeName());
467 if(currEl->getFirstChild() != NULL &&
468 currEl->getFirstChild()->getNodeType() ==
469 xercesc::DOMNode::TEXT_NODE)
473 std::cout <<
" value='"
474 << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue())) <<
"'";
476 *out <<
" value='" << (XML_TO_CHAR(currEl->getFirstChild()->getNodeValue()))
480 xercesc::DOMNodeList* nodeList = currEl->getChildNodes();
484 std::cout << ((nodeList->getLength() == 0 ||
485 (nodeList->getLength() == 1 &&
486 currEl->getFirstChild()->getNodeType() ==
487 xercesc::DOMNode::TEXT_NODE))
491 <<
" len:" << nodeList->getLength() << std::endl;
493 *out << ((nodeList->getLength() == 0 ||
494 (nodeList->getLength() == 1 &&
495 currEl->getFirstChild()->getNodeType() == xercesc::DOMNode::TEXT_NODE))
501 std::string newTabStr = tabStr +
"\t";
502 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
503 if(nodeList->item(i)->getNodeType() !=
504 xercesc::DOMNode::TEXT_NODE)
505 recursiveOutputXmlDocument(
506 (xercesc::DOMElement*)(nodeList->item(i)), out, dispStdOut, newTabStr);
509 if(nodeList->getLength() > 1 ||
510 (nodeList->getLength() == 1 &&
511 currEl->getFirstChild()->getNodeType() != xercesc::DOMNode::TEXT_NODE))
514 __COUT__ << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
517 *out << tabStr <<
"</" << XML_TO_CHAR(currEl->getNodeName()) <<
">"
608 std::string XmlDocument::escapeString(std::string inString,
bool allowWhiteSpace)
612 unsigned int ws = -1;
615 for(
unsigned int i = 0; i < inString.length(); i++)
616 if(inString[i] !=
' ')
619 __COUT__ << inString[i] <<
":" << (int)inString[i] <<
":" << inString
623 if(inString[i] ==
'\r' || inString[i] ==
'\n' ||
624 inString[i] ==
'\t' ||
627 (inString[i] >
char(126) &&
628 inString[i] < char(161)))
639 sprintf(htmlTmp,
"&#%3.3d", inString[i]);
640 inString.insert(i, htmlTmp);
658 "        ");
659 inString.insert(i, htmlTmp);
667 sprintf(htmlTmp,
"	");
668 inString.insert(i, htmlTmp);
680 inString.erase(i, 1);
684 __COUT__ << inString << std::endl;
689 __COUT__ << inString << std::endl;
692 if(inString[i] ==
'\"' || inString[i] ==
'\'')
695 (inString[i] ==
'\'')
698 inString.replace(i + 5, 1, 1,
';');
702 else if(inString[i] ==
'&')
704 inString.insert(i,
"&");
705 inString.replace(i + 4, 1, 1,
';');
708 else if(inString[i] ==
'<' || inString[i] ==
'>')
715 inString.replace(i + 3, 1, 1,
';');
718 else if(inString[i] >=
char(161) &&
719 inString[i] <=
char(255))
721 sprintf(htmlTmp,
"&#%3.3d", inString[i]);
722 inString.insert(i, htmlTmp);
723 inString.replace(i + 5, 1, 1,
';');
728 __COUT__ << inString << std::endl;
732 else if(allowWhiteSpace)
740 inString.insert(i,
" ");
743 inString.insert(i,
" ");
744 inString.replace(i + 5, 1, 1,
';');
750 __COUT__ << inString.size() <<
" " << ws << std::endl;
755 __COUT__ << inString.size() <<
" " << inString << std::endl;
761 if(ws == (
unsigned int)-1)
763 return inString.substr(0, ws + 1);
769 void XmlDocument::recursiveRemoveChild(xercesc::DOMElement* childEl,
770 xercesc::DOMElement* parentEl)
773 xercesc::DOMNodeList* nodeList =
774 childEl->getChildNodes();
775 for(
unsigned int i = 0; i < nodeList->getLength(); ++i)
776 recursiveRemoveChild(
777 (xercesc::DOMElement*)(nodeList->item(nodeList->getLength() - 1 - i)),
781 parentEl->removeChild(childEl);
789 void XmlDocument::saveXmlDocument(std::string filePath)
791 __COUT__ <<
"Saving theDocument_ to file: " << filePath << std::endl;
796 xercesc::DOMImplementation* saveImplementation =
797 xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"LS"));
801 #if _XERCES_VERSION >= 30000
806 xercesc::DOMLSSerializer* serializer =
807 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSSerializer();
810 if(serializer->getDomConfig()->canSetParameter(
811 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true))
812 serializer->getDomConfig()->setParameter(
813 xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
816 serializer->setNewLine(CONVERT_TO_XML(
"\r\n"));
822 xercesc::XMLFormatTarget* formatTarget;
826 formatTarget =
new xercesc::LocalFileFormatTarget(filePath.c_str());
830 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
831 serializer->release();
838 xercesc::DOMLSOutput* output =
839 ((xercesc::DOMImplementationLS*)saveImplementation)->createLSOutput();
842 output->setByteStream(formatTarget);
844 serializer->write(theDocument_, output);
845 serializer->release();
850 xercesc::DOMWriter* serializer =
851 ((xercesc::DOMImplementationLS*)saveImplementation)->createDOMWriter();
852 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
863 XMLCh* tempFilePath = xercesc::XMLString::transcode(filePath.c_str());
864 xercesc::XMLFormatTarget* formatTarget;
867 formatTarget =
new xercesc::LocalFileFormatTarget(tempFilePath);
871 __COUT__ <<
"Inaccessible file path: " << filePath << std::endl;
872 serializer->release();
873 xercesc::XMLString::release(&tempFilePath);
879 serializer->writeNode(formatTarget, *theDocument_);
880 serializer->release();
881 xercesc::XMLString::release(&tempFilePath);
888 #if _XERCES_VERSION >= 30000
898 bool XmlDocument::loadXmlDocument(std::string filePath)
900 __COUT__ <<
"Loading theDocument_ from file: " << filePath << std::endl;
902 struct stat fileStatus;
904 if(stat(filePath.c_str(), &fileStatus) != 0)
906 __COUT__ <<
"File not accessible." << std::endl;
914 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
916 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
917 parser->setDoNamespaces(
true);
918 parser->setDoSchema(
true);
919 parser->useCachedGrammarInParse(
false);
923 parser->parse(filePath.c_str());
926 theDocument_ = parser->adoptDocument();
931 rootElement_ = theDocument_->getDocumentElement();
933 throw(std::runtime_error(
"empty XML theDocument_"));
935 catch(xercesc::XMLException& e)
937 __COUT__ <<
"Error parsing file." << std::endl;