This tutorial assumes that you've read and fully understand the basic usage and more about content handlers tutorials. If not, go back and read it!

You're now happily importing files into your database using your newly written import app from the previous tutorial, but now need to import a file with a slightly different format:

<customers>
	<client>
		<companyName>Al Bundy's shoes</companyName>
		<companyAddress>No hope lane 34</companyAddressk>
		<phoneNr>55528974637</phoneNr>
	</client>
	<client>
		<companyName>Bob's fries</companyName>
		<companyAddress>No name avenue 56</companyAddress>
		<phoneNr>555968273328</phoneNr>
	</client>
</customers>

You could add modify the main import code to take the other format into account, but that would make the could unmaintable and difficult to read. A better option would be to write a class that converts the format of the file on the fly. Such a class would look something like this:

#include <SDXContentHandler.h>

class FormatConverter : public SDX::ContentHandler {
	public:
		FormatConverter(SDX::ContentHandler* nextInChain) :
			m_nextInChain(nextInChain)
		{
		}

		void startDocument(){ m_nextInChain->startDocument(); }
		void endDocument(){ m_nextInChain->endDocument(); }

		void startNode(std::string name){
			if(name == "companyName")
				name = "company";
			else if(name == "companyAddress")
				name = "address";
			else if(name == "phoneNr")
				name = "phone";
			else if(name == "client")
				name = "customer";

			m_nextInChain->startNode(name);
		}
		void endNode(){ m_nextInChain->endDocument(); }

		void writeAttribute(std::string name, std::string value){
			m_nextInChain->writeAttribute(name, value);
		}
	private:
		SDX::ContentHandler* m_nextInChain;
};

Pretty simple, isn't it? This class simply passes through all the commands it gets. When it gets the command to start a node, it looks for something to convert and then passes it to the next content handler. While this example is pretty straightforward, more complex situations could be handled in the same way. In this way, format specific issues stay out of your main import code, which could easily be very complicated already. Applying this to the example from the basic usage tutorial the full source code now looks like this:

// SDX
#include <SDXDocumentBuilder.h>
#include <SDXXMLFileReader.h>

// Dummy DB funtions
void startRecord();
void writeField(std::string name, std::string value);
void writeField(std::string name, int value);
void endRecord();

#include <SDXContentHandler.h>
class FormatConverter : public SDX::ContentHandler {
	public:
		FormatConverter(SDX::ContentHandler* nextInChain) :
			m_nextInChain(nextInChain)
		{
		}

		void startDocument(){ m_nextInChain->startDocument(); }
		void endDocument(){ m_nextInChain->endDocument(); }

		void startNode(std::string name){
			if(name == "companyName")
				name = "company";
			else if(name == "companyAddress")
				name = "address";
			else if(name == "phoneNr")
				name = "phone";
			else if(name == "client")
				name = "customer";

			m_nextInChain->startNode(name);
		}
		void endNode(){ m_nextInChain->endDocument(); }

		void writeAttribute(std::string name, std::string value){
			m_nextInChain->writeAttribute(name, value);
		}
	private:
		SDX::ContentHandler* m_nextInChain;
};

static bool otherFormat = true;

int main(int argc, char** argv){
	SDX::ContentHandler* docBuilder = new SDX::Helpers::DocumentBuilder;

	SDX::ContentHandler* formatConverter = 0;
	if(otherFormat)
		formatConverter = new FormatConverter(&docBuilder);

	SDX::Formats::XmlFileReader iFile("customers.xml",
		formatConverter ? formatConverter : &docBuilder);

	if(!iFile.read()){
		cerr << "File processing failed: " << iFile.getError() << endl;
		return 1;
	}

	vector<SDX::Node*> customers(docBuilder.getDocument()->getChildren("customer"));
	for(int i = 0; i < customers.size(); ++i){
		startRecord();

		std::string fieldValue;
		if(customers[i]->getNodeAttributeValue(&fieldValue, "company"))
			writeField("company", fieldValue);
		if(customers[i]->getNodeAttributeValue(&fieldValue, "address"))
			writeField("address", fieldValue);

		int phoneNumber;
		if(customers[i]->getNodeAttributeValue(&phoneNumber, "phone"))
			writeField("address", phoneNumber);

		endRecord();
	}

	return 0;
}