rusle2XML.cc [tools/Rusle2SoilsXMLCreator/pg/rusle2_from_ssurgo_build_newbackup] Revision:   Date:
#include <iostream>
#include <string>
#include <cstring>
#include <boost/lexical_cast.hpp>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
#include "rusle2_from_ssurgo.h"

using namespace std;
using boost::lexical_cast;


/**
 * ConvertInput:
 * @in: string in a given encoding
 * @encoding: the encoding used
 *
 * Converts @in into UTF-8 for processing with libxml2 APIs
 *
 * Returns the converted UTF-8 string, or NULL in case of error.
 */
xmlChar *
ConvertInput(const char *in, const char *encoding)
{
    xmlChar *out;
    int ret;
    int size;
    int out_size;
    int temp;
    xmlCharEncodingHandlerPtr handler;

    if (in == 0)
        return 0;

    handler = xmlFindCharEncodingHandler(encoding);

    if (!handler) {
        printf("ConvertInput: no encoding handler found for '%s'\n",
               encoding ? encoding : "");
        return 0;
    }

    size = (int) strlen(in) + 1;
    out_size = size * 2 - 1;
    out = (unsigned char *) xmlMalloc((size_t) out_size);

    if (out != 0) {
        temp = size - 1;
        ret = handler->input(out, &out_size, (const xmlChar *) in, &temp);
        if ((ret < 0) || (temp - size + 1)) {
            if (ret < 0) {
                printf("ConvertInput: conversion wasn't successful.\n");
            } else {
                printf
                    ("ConvertInput: conversion wasn't successful. converted: %i octets.\n",
                     temp);
            }

            xmlFree(out);
            out = 0;
        } else {
            out = (unsigned char *) xmlRealloc(out, out_size + 1);
            out[out_size] = 0;  /*null terminating out */
        }
    } else {
        printf("ConvertInput: no mem\n");
    }

    return out;
}

/* AttrXML: 
 * @writer : libxml2 text writer
 * @pszTag : The element tag for this attr type (ex: "Flt", "Bol",...)
 * @pszRusle2Name : Name Element, this is expected in all cases.
 * @value : Value element, this is expected in all cases.
 * @pszDims : Uknown...number of dimensions? Only used in map unit elements...
 * @pszUnit : Unit of value, not always present but usually is (when there are units!)
 * 
 * Writes to xml writer object @writer an element tag defined by attributes and data passed in
 * Something like below would be created
 * <@pszTag>
 *	<Name>@pszRusle2Name</Name>
 *	<Data>@value</data>
 * 	<dims>@pszDims</dims>
 * 	<Unit>@pszUnit</Unit>
 * </@pszTag>
 */
int 
AttrXML (xmlTextWriterPtr writer, string pszTag, string pszRusle2Name, string value, string pszDims, string pszUnit )
{

	/* Start pszTag */
	int rc = xmlTextWriterStartElement(writer, BAD_CAST pszTag.c_str());

	/* Name Element */
	if( rc >= 0 )
		rc = xmlTextWriterWriteElement(writer, BAD_CAST "Name", ConvertInput(pszRusle2Name.c_str(), MY_ENCODING) );
	
	/* Value Element */
	if( rc >= 0 )
		rc = xmlTextWriterWriteElement(writer, BAD_CAST "Data", ConvertInput(value.c_str(), MY_ENCODING) );

	/* Dims Element
	*	Not always present
	*/
	if( rc >= 0 && pszDims.length() > 0 )
		rc = xmlTextWriterWriteElement(writer, BAD_CAST "Dims", ConvertInput(pszDims.c_str(), MY_ENCODING) );
	
	/* There was an RX_VARIANT_TEMPLATE item commented out right here */
	/* Element was called "Var" and seemed to specify cumulative or not... */	

	/* Unit Element
	*	Not always present
	*/
	if( rc >= 0 && pszUnit.length() > 0 )
		rc = xmlTextWriterWriteElement(writer, BAD_CAST "Unit", ConvertInput(pszUnit.c_str(), MY_ENCODING) );

	
	/* End pszTag */
	if( rc >= 0 )
		rc = xmlTextWriterEndElement(writer);

	return rc;		
}

/*
 * AttrXML:
 * @writer : libxml2 text writer
 * @pszTag : The element tag for this attr type (ex: "Flt", "Bol",...)
 * @pszRusle2Name : Name Element, this is expected in all cases.
 * @low : Low value element
 * @rep : Representative value element
 * @high : High value element
 * @pszDims : Uknown...number of dimensions? Only used in map unit elements...
 * @pszUnit : Unit of value, not always present but usually is (when there are units!)
 *
 * Create an XML element for an attribute and data
 * This template includes the low, representative, and high values
 * It evaluates to see if the rep value is valid or not
 * If not it takes a simple average of high and low, then sends that value off to create the XML element and data
 * 
 * Once value is determined to be the representative value or the average of high/low, we create the element by:
 * AttrXML( @writer, @pszTag, @pszRusle2Name, @value, @pszDims, @pszUnit)
 */
int
AttrXML (xmlTextWriterPtr writer, string pszTag, string pszRusle2Name, string low, string rep, string high, string pszDims, string pszUnit ) 
{

	/* Use representitive value if possible */
	/* If rep value is null, try to do a simple average */
	string value = rep;
	if( rep.length() <= 0 )
		value = lexical_cast<string>((atof(low.c_str()) + atof(high.c_str())) / 2);

	/* If nothing still...throw a NaN */
	if ( value == "" )
			value = "NaN";

	return AttrXML( writer, pszTag, pszRusle2Name, value, pszDims, pszUnit );
	
}