7#include "xmlBase/Dom.h"
8#include <xercesc/dom/DOMCharacterData.hpp>
9#include <xercesc/dom/DOMDocument.hpp>
10#include <xercesc/dom/DOMElement.hpp>
11#include <xercesc/dom/DOMException.hpp>
12#include <xercesc/dom/DOMNamedNodeMap.hpp>
13#include <xercesc/dom/DOMNodeList.hpp>
14#include <xercesc/dom/DOMTreeWalker.hpp>
15#include <xercesc/util/PlatformUtils.hpp>
16#include <xercesc/util/TransService.hpp>
17#include <xercesc/util/XMLString.hpp>
19#include "facilities/Util.h"
31 XERCES_CPP_NAMESPACE_USE
33 DOMTreeWalker* makeWalker(
const DOMNode* node ) {
34 if ( !node )
return 0;
35 DOMDocument* doc = node->getOwnerDocument();
36 unsigned long whatToShow = DOMNodeFilter::SHOW_ELEMENT;
39 DOMNode* casted =
const_cast<DOMNode*
>( node );
41 DOMTreeWalker* walk = doc->createTreeWalker( casted, whatToShow, 0, expand );
47 XERCES_CPP_NAMESPACE_USE
49 XMLLCPTranscoder* Dom::transcoder = 0;
50 char* Dom::transBuf = 0;
52 unsigned int Dom::transBufSize = 1000;
53 XMLCh* Dom::xmlchBuf = 0;
55 unsigned int Dom::xmlchBufSize = 200;
56 XMLCh* Dom::xmlchStar = 0;
60 if ( !xmlchStar ) xmlchStar = XMLString::transcode(
"*" );
62 {
throw NullNode(
"from xmlBase::Dom::findFirstChildByName. Null parent arg." ); }
64 XMLCh* xmlchName = XMLString::transcode( name );
66 DOMTreeWalker* walk = makeWalker( parent );
67 DOMElement* child =
static_cast<DOMElement*
>( walk->firstChild() );
68 if ( XMLString::equals( xmlchName, xmlchStar ) )
return child;
70 if ( !child )
return 0;
72 while ( !XMLString::equals( child->getNodeName(), xmlchName ) )
74 child =
static_cast<DOMElement*
>( walk->nextSibling() );
75 if ( !child )
return 0;
78 XMLString::release( &xmlchName );
91 if ( !child ) {
throw NullNode(
"from xmlBase::Dom::getSiblingElement. Null argument" ); }
93 DOMNode* sib = child->getNextSibling();
97 if ( sib->getNodeType() == DOMNode::ELEMENT_NODE )
99 DOMElement* eltSib =
static_cast<DOMElement*
>( sib );
103 sib = sib->getNextSibling();
110 const DOMElement* elt =
static_cast<const DOMElement*
>( parent );
115 XMLCh* idChars = XMLString::transcode(
id.c_str() );
116 DOMElement* elt = doc->getElementById( idChars );
117 XMLString::release( &idChars );
123 {
throw NullNode(
"Null node argument supplied to xmlBase::Dom::getNodeName" ); }
124 const XMLCh* name = node->getNodeName();
125 if ( !name )
return std::string(
"" );
127 char* chrName = XMLString::transcode( name );
129 std::string strName = std::string( chrName );
130 XMLString::release( &chrName );
138 {
throw NullNode(
"Null dom element argument to xmlBase::Dom::checkTagName" ); }
139 if ( tagName == std::string(
"*" ) )
return true;
140 XMLCh* xmlchTagName = XMLString::transcode( tagName.c_str() );
141 bool ret = XMLString::equals( xmlchTagName, element->getTagName() );
142 XMLString::release( &xmlchTagName );
147 std::vector<DOMElement*>& children,
bool clear ) {
149 {
throw NullNode(
"from xmlBase::Dom::getChildrenByTagName. Null parent arg" ); }
150 if ( clear ) children.clear();
154 if (
checkTagName( child, tagName ) ) { children.push_back( child ); }
160 std::vector<DOMElement*>& children,
bool clear ) {
162 {
throw NullNode(
"from xmlBase::Dom::getChildrenByTagName. Null parent arg" ); }
163 if ( clear ) children.clear();
164 XMLCh* xmlchTagName = XMLString::transcode( tagName.c_str() );
166 DOMNodeList* list = parent->getElementsByTagName( xmlchTagName );
167 XMLString::release( &xmlchTagName );
168 unsigned int nItem = list->getLength();
169 for (
unsigned int iItem = 0; iItem < nItem; iItem++ )
170 { children.push_back(
static_cast<DOMElement*
>( list->item( iItem ) ) ); }
176 if ( clear ) atts.clear();
177 DOMNamedNodeMap* nodeMap = node->getAttributes();
178 unsigned int nAtts = nodeMap->getLength();
180 for (
unsigned iAtt = 0; iAtt < nAtts; iAtt++ )
182 DOMNode* attNode = nodeMap->item( iAtt );
189 if ( node == 0 )
return ret;
190 if ( node->getNodeType() != DOMNode::ELEMENT_NODE )
return ret;
192 const DOMElement* elt =
static_cast<const DOMElement*
>( node );
193 XMLCh* xmlchAttName = XMLString::transcode( attName );
194 ret = ( elt->getAttributeNode( xmlchAttName ) != 0 );
195 XMLString::release( &xmlchAttName );
200 if ( elt == 0 ) {
throw NullNode(
"from xmlBase::Dom::getAttribute. Null argument" ); }
202 XMLCh* xmlchAttName = XMLString::transcode( attName );
203 const XMLCh* attValue = elt->getAttribute( xmlchAttName );
204 XMLString::release( &xmlchAttName );
206 if ( attValue == 0 )
return std::string(
"" );
208 char* chrAttValue = XMLString::transcode( attValue );
209 std::string strValue = std::string( chrAttValue );
210 XMLString::release( &chrAttValue );
220 if ( elt == 0 ) {
throw NullNode(
"from xmlBase::Dom::getAttribute. Null argument" ); }
222 if ( elt->getNodeType() != DOMNode::ELEMENT_NODE )
223 {
throw NullNode(
"from xmlBase::Dom::getAttribute. Non-element argument" ); }
224 return getAttribute(
static_cast<const DOMElement*
>( elt ), attName );
234 if ( stringValue == std::string(
"" ) )
235 {
throw NullNode(
"from xmlBase::Dom::getDoubleAttribute. non-existent attribute" ); }
247 std::vector<double>& values,
bool clear ) {
249 std::vector<std::string> tokens;
250 if ( clear ) values.clear();
252 if ( stringValue.size() == 0 )
return nVals;
258 unsigned nToken = tokens.size();
259 for (
unsigned iToken = 0; iToken < nToken; iToken++ )
272 std::vector<float>& values,
bool clear ) {
274 std::vector<std::string> tokens;
275 if ( clear ) values.clear();
277 if ( stringValue.size() == 0 )
return nVals;
283 unsigned nToken = tokens.size();
284 for (
unsigned iToken = 0; iToken < nToken; iToken++ )
300 if ( stringValue == std::string(
"" ) )
301 {
throw NullNode(
"from xmlBase::Dom::getIntAttribute. non-existent attribute" ); }
311 std::vector<int>& values,
bool clear ) {
313 std::vector<std::string> tokens;
314 if ( clear ) values.clear();
316 if ( stringValue.size() == 0 )
return nVals;
322 unsigned nToken = tokens.size();
323 for (
unsigned iToken = 0; iToken < nToken; iToken++ )
337 short int nType = textNode->getNodeType();
339 if ( ( nType != DOMNode::TEXT_NODE ) && ( nType != DOMNode::COMMENT_NODE ) &&
340 ( nType != DOMNode::CDATA_SECTION_NODE ) )
341 {
throw WrongNodeType(
"from xmlBase::Dom::getText, argument not text node" ); }
342 const XMLCh*
t = textNode->getNodeValue();
343 if (
t == 0 )
return std::string(
"" );
344 char* chrText = XMLString::transcode(
t );
345 std::string
text = std::string( chrText );
346 XMLString::release( &chrText );
352 if ( elt->getNodeType() != DOMNode::ELEMENT_NODE )
353 {
throw WrongNodeType(
"from xmlBase::Dom::getTextContent, argument not element node" ); }
354 return (
getText( elt->getFirstChild() ) );
358 if ( elt == 0 ) {
throw NullNode(
"from xmlBase::Dom::addAttribute. null argument" ); }
364 std::ostringstream
s;
368 std::string str =
s.str();
369 XMLCh* xmlchValue = XMLString::transcode( str.c_str() );
370 XMLCh* xmlchName = XMLString::transcode( name.c_str() );
373 { elt->setAttribute( xmlchName, xmlchValue ); }
catch ( DOMException ex )
375 char* msg = XMLString::transcode( ex.msg );
376 std::cerr <<
"DOMException in xmlBase::Dom::addAttribute(double)" << std::endl;
377 std::cerr <<
"Msg: " << std::string( msg ) <<
"Code: " << ex.code << std::endl;
378 XMLString::release( &msg );
381 XMLString::release( &xmlchName );
382 XMLString::release( &xmlchValue );
386 if ( elt == 0 ) {
throw NullNode(
"from xmlBase::Dom::addAttribute. Null argument" ); }
392 std::ostringstream
s;
396 std::string str =
s.str();
398 XMLCh* xmlchValue = XMLString::transcode( str.c_str() );
399 XMLCh* xmlchName = XMLString::transcode( name.c_str() );
402 { elt->setAttribute( xmlchName, xmlchValue ); }
catch ( DOMException ex )
404 char* msg = XMLString::transcode( ex.msg );
405 std::cerr <<
"DOMException in xmlBase::Dom::addAttribute(int)" << std::endl;
406 std::cerr <<
"Msg: " << std::string( msg ) <<
"Code: " << ex.code << std::endl;
407 XMLString::release( &msg );
411 XMLString::release( &xmlchName );
412 XMLString::release( &xmlchValue );
416 if ( elt == 0 ) {
throw NullNode(
"from xmlBase::Dom::addAttribute. Null argument" ); }
422 std::ostringstream
s;
426 std::string str =
s.str();
428 XMLCh* xmlchValue = XMLString::transcode( str.c_str() );
429 XMLCh* xmlchName = XMLString::transcode( name.c_str() );
432 { elt->setAttribute( xmlchName, xmlchValue ); }
catch ( DOMException ex )
434 char* msg = XMLString::transcode( ex.msg );
435 std::cerr <<
"DOMException in xmlBase::Dom::addAttribute(unsigned int)" << std::endl;
436 std::cerr <<
"Msg: " << std::string( msg ) <<
"Code: " << ex.code << std::endl;
437 XMLString::release( &msg );
440 XMLString::release( &xmlchName );
441 XMLString::release( &xmlchValue );
446 if ( elt == 0 ) {
throw NullNode(
"from xmlBase::Dom::addAttribute. Null argument" ); }
448 XMLCh* xmlchValue = XMLString::transcode( value );
449 XMLCh* xmlchName = XMLString::transcode( name.c_str() );
452 { elt->setAttribute( xmlchName, xmlchValue ); }
catch ( DOMException ex )
454 char* msg = XMLString::transcode( ex.msg );
455 std::cerr <<
"DOMException in xmlBase::Dom::addAttribute(char*)" << std::endl;
456 std::cerr <<
"Msg: " << std::string( msg ) <<
"Code: " << ex.code << std::endl;
458 XMLString::release( &msg );
462 XMLString::release( &xmlchName );
463 XMLString::release( &xmlchValue );
468 if ( elt == 0 )
throw NullNode(
"from xmlBase::Dom::addAttribute. Null argument" );
507 if ( node == 0 ) {
throw NullNode(
"from xmlBase::Dom::printElement. Null argument" ); }
509 switch ( node->getNodeType() )
511 case DOMNode::ELEMENT_NODE: {
515 out <<
'<' << tagName;
519 typedef std::map<std::string, DOMNode*> AttMap;
521 AttMap::const_iterator it;
524 for ( it = atts.begin(); it != atts.end(); it++ )
526 std::string attName = ( *it ).first;
527 out <<
' ' << attName <<
'=';
532 DOMNode* child = node->getFirstChild();
539 child = child->getNextSibling();
544 out <<
"</" << endName <<
">";
553 case DOMNode::TEXT_NODE:
558 case DOMNode::CDATA_SECTION_NODE: {
559 out <<
"<![CDATA[" <<
getText( node ) <<
"]]>";
563 case DOMNode::COMMENT_NODE:
565 { out <<
"<!-- " <<
getText( node ) <<
"-->"; }
577 {
throw NullNode(
"from xmlBase::Dom::prettyPrintElement. Null argument" ); }
580 switch ( node->getNodeType() )
583 case DOMNode::ELEMENT_NODE: {
586 out <<
'<' << tagName;
589 typedef std::map<std::string, DOMNode*> AttMap;
591 AttMap::const_iterator it;
595 for ( it = atts.begin(); it != atts.end(); it++ )
597 std::string attName = ( *it ).first;
598 out <<
' ' << attName <<
'=';
603 DOMNode* child = node->getFirstChild();
606 out <<
'>' << std::endl;
611 child = child->getNextSibling();
616 out << prefix <<
"</" << endName <<
">" << std::endl;
621 out <<
" />" << std::endl;
625 case DOMNode::TEXT_NODE:
637 case DOMNode::CDATA_SECTION_NODE: {
639 out <<
"<![CDATA[" <<
getText( node ) <<
"]]>";
643 case DOMNode::COMMENT_NODE:
648 { out <<
"<!-- " <<
getText( node ) <<
"-->" << std::endl; }
663 elt->removeChild( child );
667 char* Dom::transToChar(
const XMLCh*
const str ) {
668 return transToChar( str, XMLString::stringLen( str ) );
671 char* Dom::transToChar(
const XMLCh*
const str,
unsigned int len ) {
675 if ( str == 0 )
return 0;
679 int status = initTrans();
680 if ( !status )
return 0;
690 if ( len + 1 > transBufSize )
692 char* tBuf =
new char[len + 1];
693 if ( !tBuf )
return 0;
694 transBufSize = len + 1;
700 ok = Dom::transcoder->transcode( str, transBuf, len );
701 return ( ok ? transBuf : 0 );
704 XMLCh* Dom::transToXMLCh(
const char*
const src ) {
707 if ( src == 0 )
return 0;
710 int status = initTrans();
711 if ( !status )
return 0;
715 unsigned int len = strlen( src ) + 1;
716 if ( len > xmlchBufSize )
718 XMLCh* tBuf =
new XMLCh[len];
719 if ( !tBuf )
return 0;
727 ok = transcoder->transcode( src, xmlchBuf, len );
728 return ( ok ? xmlchBuf : 0 );
731 int Dom::initTrans() {
732 transcoder = XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(
733 XMLPlatformUtils::fgMemoryManager );
734 if ( !transcoder )
return 0;
735 transBuf =
new char[transBufSize];
741 xmlchBuf =
new XMLCh[xmlchBufSize];
static double stringToDouble(const std::string &InStr)
static void stringTokenize(std::string input, const std::string &delimiters, std::vector< std::string > &tokens, bool clear=true)
static int stringToInt(const std::string &InStr)
Exception class used when converting from string to numeric type.
static std::string getTagName(const DOMElement *node)
static void getChildrenByTagName(const DOMElement *parent, const std::string &tagName, std::vector< DOMElement * > &children, bool clear=true)
static void addAttribute(DOMElement *elt, std::string name, double value)
Add attribute of type double to a DOM element, DOMString att name.
static int getIntAttribute(const DOMNode *elt, std::string attName)
static DOMElement * getSiblingElement(const DOMNode *child)
Return next element sibling, if any.
static unsigned getFloatsAttribute(const DOMNode *elt, std::string attName, std::vector< float > &values, bool clear=true)
static std::string getTextContent(const DOMElement *elt)
static void prettyPrintElement(DOMNode *elt, std::ostream &out, std::string prefix)
static void getAttributeNodeMap(const DOMNode *elt, std::map< std::string, DOMNode * > &atts, bool clear=true)
static void printElement(DOMNode *elt, std::ostream &out)
static bool hasAttribute(const DOMNode *elt, const char *attName)
static double getDoubleAttribute(const DOMNode *elt, std::string attName)
static DOMElement * getElementById(const DOMDocument *doc, const std::string &id)
static std::string getNodeName(const DOMNode *elt)
static std::string getAttribute(const DOMElement *elt, const char *attName)
static DOMElement * findFirstChildByName(const DOMElement *parent, const char *const name)
static void getDescendantsByTagName(const DOMElement *parent, const std::string &tagName, std::vector< DOMElement * > &children, bool clear=true)
static unsigned getDoublesAttribute(const DOMNode *elt, std::string attName, std::vector< double > &values, bool clear=true)
static DOMElement * getFirstChildElement(const DOMNode *parent)
Get first child which is an element node, if any.
static unsigned getIntsAttribute(const DOMNode *elt, std::string attName, std::vector< int > &values, bool clear=true)
static void prune(DOMElement *elt)
static std::string getText(const DOMNode *textNode)
static bool checkTagName(const DOMElement *element, const std::string &tagName)