The Apache project's Xerces-C libraries support the DOM approach to XML parsing.
The entire XML file is imported into memory and the data is held as nodes in a data tree which can be traversed for information.
Unpack the downloaded file: tar -xzf xerces-c-src_2_7_0.tar.gz
Set the XERCESCROOT environment variable to the directory which contains the source code: (bash shell example)
export XERCESCROOT=/home/user-id/src/xerces-c-src_2_7_0
Go to source directory: cd xerces-c-src_2_7_0/src/xercesc
Run script which runs "configure": runConfigure -plinux -cgcc -xg++ -C--prefix=/opt/ApacheXML
This will install development files such as include header files and libraries in "/opt" so compiler flags and linker flags are required:
Compiler flags: -I/opt/include
Linker flags: -L/opt/lib -lxerces-c
Creating an RPM for Xerces-C libraries:
The downloaded gzipped tar file can be used to generate an RPM:
rpmbuild -ta xerces-c-src_2_7_0.tar.gz
[Potential Pitfall]: If you download the package
"xerces-c-current.tar.gz", you may have to rename it to make it work. The error message will give you a clue as to what to name it.
In this example:
mv xerces-c-current.tar.gz xerces-c-src_2_7_0.tar.gz
Then execute the "rpmbuild" command.
[Potential Pitfall]: If building as a Linux user, you will have to open up the directory permissions of /use/src/redhat/... or build as root user.
Install the RPMs with the command: rpm -ivh xerces-c-2.7.0-3.i586.rpm xerces-c-devel-2.7.0-3.i586.rpm xerces-c-doc-2.7.0-3.i586.rpm
Installing the RPM will place files in:
Xerces-c RPM:
/usr/lib
/usr/bin
Xerces-c doc RPM: /usr/share/xerces-c/
Xerces-c devel RPM:
/usr/include/xerces-c/
/usr/share/doc/packages/xerces-c-doc/
Because the development libraries and include files are
located in the regular system areas expected by the compiler, the only
linker flag required is "-lxerces-c"
/** * Constructor initializes xerces-C libraries. * The XML tags and attributes which we seek are defined. * The xerces-C DOM parser infrastructure is initialized. */
// Tags and attributes used in XML file. // Can't call transcode till after Xerces Initialize() TAG_root = XMLString::transcode("root"); TAG_ApplicationSettings = XMLString::transcode("ApplicationSettings"); ATTR_OptionA = XMLString::transcode("option_a"); ATTR_OptionB = XMLString::transcode("option_b");
m_ConfigFileParser = new XercesDOMParser; }
/** * Class destructor frees memory used to hold the XML tag and * attribute definitions. It als terminates use of the xerces-C * framework. */
/** * This function: * - Tests the access and availability of the XML configuration file. * - Configures the xerces-c DOM parser. * - Reads and extracts the pertinent information from the XML config file. * * @param in configFile The text string name of the HLA configuration file. */
void GetConfig::readConfigFile(string& configFile) throw( std::runtime_error ) { // Test to see if the file is ok.
struct stat fileStatus;
int iretStat = stat(configFile.c_str(), &fileStatus); if( iretStat == ENOENT ) throw ( std::runtime_error("Path file_name does not exist, or path is an empty string.") ); else if( iretStat == ENOTDIR ) throw ( std::runtime_error("A component of the path is not a directory.")); else if( iretStat == ELOOP ) throw ( std::runtime_error("Too many symbolic links encountered while traversing the path.")); else if( iretStat == EACCES ) throw ( std::runtime_error("Permission denied.")); else if( iretStat == ENAMETOOLONG ) throw ( std::runtime_error("File can not be read\n"));
// Parse XML file for tags of interest: "ApplicationSettings" // Look one level nested within "root". (child of root)
DOMNodeList* children = elementRoot->getChildNodes(); const XMLSize_t nodeCount = children->getLength();
// For all nodes, children of "root" in the XML tree.
for( XMLSize_t xx = 0; xx < nodeCount; ++xx ) { DOMNode* currentNode = children->item(xx); if( currentNode->getNodeType() && // true is not NULL currentNode->getNodeType() == DOMNode::ELEMENT_NODE ) // is element { // Found node which is an Element. Re-cast node as element DOMElement* currentElement = dynamic_cast< xercesc::DOMElement* >( currentNode ); if( XMLString::equals(currentElement->getTagName(), TAG_ApplicationSettings)) { // Already tested node as type element and of name "ApplicationSettings". // Read attributes of element "ApplicationSettings". const XMLCh* xmlch_OptionA = currentElement->getAttribute(ATTR_OptionA); m_OptionA = XMLString::transcode(xmlch_OptionA);
break; // Data found. No need to look at other elements in tree. } } } } catch( xercesc::XMLException& e ) { char* message = xercesc::XMLString::transcode( e.getMessage() ); ostringstream errBuf; errBuf << "Error parsing file: " << message << flush; XMLString::release( &message ); } }
#ifdef MAIN_TEST /* This main is provided for unit test of the class. */
int main() { string configFile="sample.xml"; // stat file. Get ambigious segfault otherwise.
Professional XML Development with Apache Tools : Xerces, Xalan, FOP, Cocoon, Axis, Xindice
by Theodore W. Leung
ISBN #0764543555, Wrox Press
Dr. Dobb's Journal
Free subscription to the premier resource for
professional programmers and software developers. Multi-language and
multi-platform with program listings, coding tips, design issue
discussions and algorithms. Subscribe here!