Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Make the most of Xerces-C++, Part 1

A parsing how-to for C++ programmers

Return to article.


Listing 7. Example SAX event-handler implementation
                // GraphHandler.cpp
#include "GraphHandler.h"
#include <xercesc/sax2/Attributes.hpp>
#include <stdio.h>
#include "XercesString.h"
#include <float.h>

static const bool bDebug = false;

void GraphHandler::startDocument()
{
  if (bDebug) printf("starting...\n");
}

// given a value, minimum, maximum and overall discrete number of tiles;
// computes how many tiles or blocks will be displaced by the value.
static int tiles(double fValue, double fMin, double fMax, int nSpan)
{
  double fDel = fMax - fMin;
  fValue -= fMin;
  if (fDel <= FLT_MIN) fValue = 0.;
  else fValue /= (fMax - fMin);
  return (int)(fValue * nSpan);
}

// returns a null terminated string whose length 
// is the requested span (up to some limit).
static const char *bars(int nSpan)
{
  static const char strBars[] = 
    "########################################"
	"########################################";
  const int kLimit = sizeof strBars - 1;
  if (nSpan > kLimit) nSpan = kLimit;
  return &strBars[kLimit - nSpan];
}

void GraphHandler::endDocument()
{
  int nDex = 0;
  double fMin = 0.0, fMax = 0.0;
  if (bDebug) printf("...ends.\n");

  const unsigned kLimit = mList.size();
  if (bDebug)
  {
    printf("Department               Sales Inventory     Labor\n");
    printf("-------------------- --------- --------- ---------\n");
  }
  for (nDex = 0; nDex < kLimit; nDex++)
  {
    double fValue = mList[nDex].mSales;
    if (!nDex)
      fMin = fMax = fValue;
    else
    {
      if (fValue > fMax) fMax = fValue;
      else if (fValue < fMin) fMin = fValue;
    }
    if (bDebug)
    {
      char *strName = XMLString::transcode(mList[nDex].mName);
      printf("%-20.20s %9.2f %9.2f %9.2f\n", strName, mList[nDex].mSales, 
	    mList[nDex].mInventory, mList[nDex].mLabor);
	  XMLString::release(&strName);
    }
  }
  const int nSpan = 70;
  fMin *= 0.8;
  for (nDex = 0; nDex < kLimit; nDex++)
  {
    int nWidth = tiles(mList[nDex].mSales, fMin, fMax, nSpan);
    char *strName = XMLString::transcode(mList[nDex].mName);
    printf("%-20.20s (%7.0f) %s\n", strName, mList[nDex].mSales, bars(nWidth) );
	XMLString::release(&strName);
  }
}

void GraphHandler::startElement(
		const XMLCh* const uri, 
		const XMLCh* const localname, 
		const XMLCh* const qname, 
		const Attributes& attrs)
{
  if (bDebug) printf("element...[%ws, %ws, %ws]\n", uri, localname, qname);

  const XercesString kstrFigures("figures");
  const XercesString kstrType("type");
  const XercesString kstrValue("value");
  const XercesString kstrDepartment("department");
  const XercesString kstrSales("sales");
  const XercesString kstrLabel("label");
  const XercesString kstrLabor("labor");
  const XercesString kstrInventory("inventory");
  const XercesString kstrName("name");
  const XercesString kstrCorporate("corporate");

  if ( !XMLString::compareString(localname, kstrFigures) )
  {
    const XercesString wstrType( attrs.getValue(kstrType) );
    const XercesString wstrValue( attrs.getValue(kstrValue) );
	double fValue = wcstod(wstrValue, NULL);

    if (mList.size())
    {
      if ( !XMLString::compareString(wstrType, kstrSales) )
        mList[mList.size() - 1].mSales = fValue;
      else if ( !XMLString::compareString(wstrType, kstrInventory) )
        mList[mList.size() - 1].mInventory = fValue;
      else if ( !XMLString::compareString(wstrType, kstrLabor) )
        mList[mList.size() - 1].mLabor = fValue;
    }
  }
  else if ( !XMLString::compareString(localname, kstrDepartment) )
  {
    const XercesString wstrValue( attrs.getValue(kstrName) );
    mList.insert(mList.end(), department(wstrValue) );
  }
  else if ( !XMLString::compareString(localname, kstrCorporate) )
  {
    mName = XMLString::replicate( attrs.getValue(kstrName) );
  }
}

void GraphHandler::endElement(
  const XMLCh* const uri, 
  const XMLCh* const localname,
  const XMLCh* const qname)
{
  if (bDebug) printf("...end element.\n");
}

void GraphHandler::characters(
  const XMLCh* const chars,
  const unsigned int length)
{
  if (!bDebug) return;
  char *strChars = new char [length+1];
  XMLString::transcode(chars, strChars, length);
  strChars[length] = 0;
  printf("chars [ %-0.*s ] \n", length, strChars);
  delete[] strChars;
}

Return to article.