DOMCount.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:17k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: DOMCount.cpp,v 1.37 2003/03/19 15:10:56 gareth Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/PlatformUtils.hpp>
  63. #include <xercesc/parsers/AbstractDOMParser.hpp>
  64. #include <xercesc/dom/DOMImplementation.hpp>
  65. #include <xercesc/dom/DOMImplementationLS.hpp>
  66. #include <xercesc/dom/DOMImplementationRegistry.hpp>
  67. #include <xercesc/dom/DOMBuilder.hpp>
  68. #include <xercesc/dom/DOMException.hpp>
  69. #include <xercesc/dom/DOMDocument.hpp>
  70. #include <xercesc/dom/DOMNodeList.hpp>
  71. #include <xercesc/dom/DOMError.hpp>
  72. #include <xercesc/dom/DOMLocator.hpp>
  73. #include <xercesc/dom/DOMNamedNodeMap.hpp>
  74. #include <xercesc/dom/DOMAttr.hpp>
  75. #include "DOMCount.hpp"
  76. #include <string.h>
  77. #include <stdlib.h>
  78. #include <fstream.h>
  79. // ---------------------------------------------------------------------------
  80. //  This is a simple program which invokes the DOMParser to build a DOM
  81. //  tree for the specified input file. It then walks the tree and counts
  82. //  the number of elements. The element count is then printed.
  83. // ---------------------------------------------------------------------------
  84. static void usage()
  85. {
  86.     cout << "nUsage:n"
  87.             "    DOMCount [options] <XML file | List file>nn"
  88.             "This program invokes the DOMBuilder, builds the DOM tree,n"
  89.             "and then prints the number of elements found in each XML file.nn"
  90.             "Options:n"
  91.             "    -l          Indicate the input file is a List File that has a list of xml files.n"
  92.             "                Default to off (Input file is an XML file).n"
  93.             "    -v=xxx      Validation scheme [always | never | auto*].n"
  94.             "    -n          Enable namespace processing. Defaults to off.n"
  95.             "    -s          Enable schema processing. Defaults to off.n"
  96.             "    -f          Enable full schema constraint checking. Defaults to off.n"
  97.             "    -locale=ll_CC specify the locale, default: en_US.n"
  98.             "    -p          Print out names of elements and attributes encountered.n"
  99.     "    -?          Show this help.nn"
  100.             "  * = Default if not provided explicitly.n"
  101.          << endl;
  102. }
  103. // ---------------------------------------------------------------------------
  104. //
  105. //  Recursively Count up the total number of child Elements under the specified Node.
  106. //  Process attributes of the node, if any.
  107. //
  108. // ---------------------------------------------------------------------------
  109. static int countChildElements(DOMNode *n, bool printOutEncounteredEles)
  110. {
  111.     DOMNode *child;
  112.     int count = 0;
  113.     if (n) {
  114.         if (n->getNodeType() == DOMNode::ELEMENT_NODE)
  115. {
  116.             if(printOutEncounteredEles) {
  117.                 char *name = XMLString::transcode(n->getNodeName());
  118.                 cout <<"----------------------------------------------------------"<<endl;
  119.                 cout <<"Encountered Element : "<< name << endl;
  120.                 
  121.                 XMLString::release(&name);
  122.                 if(n->hasAttributes()) {
  123.                     // get all the attributes of the node
  124.                     DOMNamedNodeMap *pAttributes = n->getAttributes();
  125.                     int nSize = pAttributes->getLength();
  126.                     cout <<"tAttributes" << endl;
  127.                     cout <<"t----------" << endl;
  128.                     for(int i=0;i<nSize;++i) {
  129.                         DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->item(i);
  130.                         // get attribute name
  131.                         char *name = XMLString::transcode(pAttributeNode->getName());
  132.                         
  133.                         cout << "t" << name << "=";
  134.                         XMLString::release(&name);
  135.                         
  136.                         // get attribute type
  137.                         name = XMLString::transcode(pAttributeNode->getValue());
  138.                         cout << name << endl;
  139.                         XMLString::release(&name);
  140.                     }
  141.                 }
  142.             }
  143. ++count;
  144. }
  145.         for (child = n->getFirstChild(); child != 0; child=child->getNextSibling())
  146.             count += countChildElements(child, printOutEncounteredEles);
  147.     }
  148.     return count;
  149. }
  150. // ---------------------------------------------------------------------------
  151. //
  152. //   main
  153. //
  154. // ---------------------------------------------------------------------------
  155. int main(int argC, char* argV[])
  156. {
  157.     // Check command line and extract arguments.
  158.     if (argC < 2)
  159.     {
  160.         usage();
  161.         return 1;
  162.     }
  163.     const char*                xmlFile = 0;
  164.     AbstractDOMParser::ValSchemes valScheme = AbstractDOMParser::Val_Auto;
  165.     bool                       doNamespaces       = false;
  166.     bool                       doSchema           = false;
  167.     bool                       schemaFullChecking = false;
  168.     bool                       doList = false;
  169.     bool                       errorOccurred = false;
  170.     bool                       recognizeNEL = false;
  171.     bool                       printOutEncounteredEles = false;
  172.     char                       localeStr[64];
  173.     memset(localeStr, 0, sizeof localeStr);
  174.     int argInd;
  175.     for (argInd = 1; argInd < argC; argInd++)
  176.     {
  177.         // Break out on first parm not starting with a dash
  178.         if (argV[argInd][0] != '-')
  179.             break;
  180.         // Watch for special case help request
  181.         if (!strcmp(argV[argInd], "-?"))
  182.         {
  183.             usage();
  184.             return 2;
  185.         }
  186.          else if (!strncmp(argV[argInd], "-v=", 3)
  187.               ||  !strncmp(argV[argInd], "-V=", 3))
  188.         {
  189.             const char* const parm = &argV[argInd][3];
  190.             if (!strcmp(parm, "never"))
  191.                 valScheme = AbstractDOMParser::Val_Never;
  192.             else if (!strcmp(parm, "auto"))
  193.                 valScheme = AbstractDOMParser::Val_Auto;
  194.             else if (!strcmp(parm, "always"))
  195.                 valScheme = AbstractDOMParser::Val_Always;
  196.             else
  197.             {
  198.                 cerr << "Unknown -v= value: " << parm << endl;
  199.                 return 2;
  200.             }
  201.         }
  202.          else if (!strcmp(argV[argInd], "-n")
  203.               ||  !strcmp(argV[argInd], "-N"))
  204.         {
  205.             doNamespaces = true;
  206.         }
  207.          else if (!strcmp(argV[argInd], "-s")
  208.               ||  !strcmp(argV[argInd], "-S"))
  209.         {
  210.             doSchema = true;
  211.         }
  212.          else if (!strcmp(argV[argInd], "-f")
  213.               ||  !strcmp(argV[argInd], "-F"))
  214.         {
  215.             schemaFullChecking = true;
  216.         }
  217.          else if (!strcmp(argV[argInd], "-l")
  218.               ||  !strcmp(argV[argInd], "-L"))
  219.         {
  220.             doList = true;
  221.         }
  222.          else if (!strcmp(argV[argInd], "-special:nel"))
  223.         {
  224.             // turning this on will lead to non-standard compliance behaviour
  225.             // it will recognize the unicode character 0x85 as new line character
  226.             // instead of regular character as specified in XML 1.0
  227.             // do not turn this on unless really necessary
  228.              recognizeNEL = true;
  229.         }
  230.          else if (!strcmp(argV[argInd], "-p")
  231.               ||  !strcmp(argV[argInd], "-P"))
  232.         {
  233.             printOutEncounteredEles = true;
  234.         }
  235.          else if (!strncmp(argV[argInd], "-locale=", 8))
  236.         {
  237.              // Get out the end of line
  238.              strcpy(localeStr, &(argV[argInd][8]));
  239.         }
  240.          else
  241.         {
  242.             cerr << "Unknown option '" << argV[argInd]
  243.                  << "', ignoring itn" << endl;
  244.         }
  245.     }
  246.     //
  247.     //  There should be only one and only one parameter left, and that
  248.     //  should be the file name.
  249.     //
  250.     if (argInd != argC - 1)
  251.     {
  252.         usage();
  253.         return 1;
  254.     }
  255.     // Initialize the XML4C system
  256.     try
  257.     {
  258.         if (strlen(localeStr))
  259.         {
  260.             XMLPlatformUtils::Initialize(localeStr);
  261.         }
  262.         else
  263.         {
  264.             XMLPlatformUtils::Initialize();
  265.         }
  266.         if (recognizeNEL)
  267.         {
  268.             XMLPlatformUtils::recognizeNEL(recognizeNEL);
  269.         }
  270.     }
  271.     catch (const XMLException& toCatch)
  272.     {
  273.          cerr << "Error during initialization! :n"
  274.               << StrX(toCatch.getMessage()) << endl;
  275.          return 1;
  276.     }
  277.     // Instantiate the DOM parser.
  278.     static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
  279.     DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
  280.     DOMBuilder        *parser = ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
  281.     parser->setFeature(XMLUni::fgDOMNamespaces, doNamespaces);
  282.     parser->setFeature(XMLUni::fgXercesSchema, doSchema);
  283.     parser->setFeature(XMLUni::fgXercesSchemaFullChecking, schemaFullChecking);
  284.     if (valScheme == AbstractDOMParser::Val_Auto)
  285.     {
  286.         parser->setFeature(XMLUni::fgDOMValidateIfSchema, true);
  287.     }
  288.     else if (valScheme == AbstractDOMParser::Val_Never)
  289.     {
  290.         parser->setFeature(XMLUni::fgDOMValidation, false);
  291.     }
  292.     else if (valScheme == AbstractDOMParser::Val_Always)
  293.     {
  294.         parser->setFeature(XMLUni::fgDOMValidation, true);
  295.     }
  296.     // enable datatype normalization - default is off
  297.     parser->setFeature(XMLUni::fgDOMDatatypeNormalization, true);
  298.     // And create our error handler and install it
  299.     DOMCountErrorHandler errorHandler;
  300.     parser->setErrorHandler(&errorHandler);
  301.     //
  302.     //  Get the starting time and kick off the parse of the indicated
  303.     //  file. Catch any exceptions that might propogate out of it.
  304.     //
  305.     unsigned long duration;
  306.     bool more = true;
  307.     ifstream fin;
  308.     // the input is a list file
  309.     if (doList)
  310.         fin.open(argV[argInd]);
  311.     if (fin.fail()) {
  312.         cerr <<"Cannot open the list file: " << argV[argInd] << endl;
  313.         return 2;
  314.     }
  315.     while (more)
  316.     {
  317.         char fURI[1000];
  318.         //initialize the array to zeros
  319.         memset(fURI,0,sizeof(fURI));
  320.         if (doList) {
  321.             if (! fin.eof() ) {
  322.                 fin.getline (fURI, sizeof(fURI));
  323.                 if (!*fURI)
  324.                     continue;
  325.                 else {
  326.                     xmlFile = fURI;
  327.                     cerr << "==Parsing== " << xmlFile << endl;
  328.                 }
  329.             }
  330.             else
  331.                 break;
  332.         }
  333.         else {
  334.             xmlFile = argV[argInd];
  335.             more = false;
  336.         }
  337.         //reset error count first
  338.         errorHandler.resetErrors();
  339.         XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = 0;
  340.         try
  341.         {
  342.             // reset document pool
  343.             parser->resetDocumentPool();
  344.             const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
  345.             doc = parser->parseURI(xmlFile);
  346.             const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
  347.             duration = endMillis - startMillis;
  348.         }
  349.         catch (const XMLException& toCatch)
  350.         {
  351.             cerr << "nError during parsing: '" << xmlFile << "'n"
  352.                  << "Exception message is:  n"
  353.                  << StrX(toCatch.getMessage()) << "n" << endl;
  354.             errorOccurred = true;
  355.             continue;
  356.         }
  357.         catch (const DOMException& toCatch)
  358.         {
  359.             const unsigned int maxChars = 2047;
  360.             XMLCh errText[maxChars + 1];
  361.             cerr << "nDOM Error during parsing: '" << xmlFile << "'n"
  362.                  << "DOMException code is:  " << toCatch.code << endl;
  363.             if (DOMImplementation::loadDOMExceptionMsg(toCatch.code, errText, maxChars))
  364.                  cerr << "Message is: " << StrX(errText) << endl;
  365.             errorOccurred = true;
  366.             continue;
  367.         }
  368.         catch (...)
  369.         {
  370.             cerr << "nUnexpected exception during parsing: '" << xmlFile << "'n";
  371.             errorOccurred = true;
  372.             continue;
  373.         }
  374.         //
  375.         //  Extract the DOM tree, get the list of all the elements and report the
  376.         //  length as the count of elements.
  377.         //
  378.         if (errorHandler.getSawErrors())
  379.         {
  380.             cout << "nErrors occurred, no output availablen" << endl;
  381.             errorOccurred = true;
  382.         }
  383.          else
  384.         {
  385.             unsigned int elementCount = 0;
  386.             if (doc) {
  387.                 elementCount = countChildElements((DOMNode*)doc->getDocumentElement(), printOutEncounteredEles);
  388.                 // test getElementsByTagName and getLength
  389.                 XMLCh xa[] = {chAsterisk, chNull};
  390.                 if (elementCount != doc->getElementsByTagName(xa)->getLength()) {
  391.                     cout << "nErrors occurred, element count is wrongn" << endl;
  392.                     errorOccurred = true;
  393.                 }
  394.             }
  395.             // Print out the stats that we collected and time taken.
  396.             cout << xmlFile << ": " << duration << " ms ("
  397.                  << elementCount << " elems)." << endl;
  398.         }
  399.     }
  400.     //
  401.     //  Delete the parser itself.  Must be done prior to calling Terminate, below.
  402.     //
  403.     parser->release();
  404.     // And call the termination method
  405.     XMLPlatformUtils::Terminate();
  406.     if (doList)
  407.         fin.close();
  408.     if (errorOccurred)
  409.         return 4;
  410.     else
  411.         return 0;
  412. }
  413. DOMCountErrorHandler::DOMCountErrorHandler() :
  414.     fSawErrors(false)
  415. {
  416. }
  417. DOMCountErrorHandler::~DOMCountErrorHandler()
  418. {
  419. }
  420. // ---------------------------------------------------------------------------
  421. //  DOMCountHandlers: Overrides of the DOM ErrorHandler interface
  422. // ---------------------------------------------------------------------------
  423. bool DOMCountErrorHandler::handleError(const DOMError& domError)
  424. {
  425.     fSawErrors = true;
  426.     if (domError.getSeverity() == DOMError::DOM_SEVERITY_WARNING)
  427.         cerr << "nWarning at file ";
  428.     else if (domError.getSeverity() == DOMError::DOM_SEVERITY_ERROR)
  429.         cerr << "nError at file ";
  430.     else
  431.         cerr << "nFatal Error at file ";
  432.     cerr << StrX(domError.getLocation()->getURI())
  433.          << ", line " << domError.getLocation()->getLineNumber()
  434.          << ", char " << domError.getLocation()->getColumnNumber()
  435.          << "n  Message: " << StrX(domError.getMessage()) << endl;
  436.     return true;
  437. }
  438. void DOMCountErrorHandler::resetErrors()
  439. {
  440.     fSawErrors = false;
  441. }