/**
 * libxml2 OME-XML writer example -- OME-XML 2008-09 Schema
 * Chris Allan <chris at glencoesoftware dot com>
 *
 * Copyright (c) 2009 Open Microscopy Environment
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

// Requires libxml2-dev package.
// Compile on Linux with:
//   gcc -lxml2 -I/usr/include/libxml2 example.c -o example

#include <stdio.h>
#include <string.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>

#define DEFAULT_ENCODING "ISO-8859-1"

#define start_document() \
	rc = xmlTextWriterStartDocument(writer, NULL, DEFAULT_ENCODING, NULL); \
	if (rc < 0) \
	{ \
		printf("Error at xmlTextWriterStartDocument.\n"); \
		return; \
	}

#define start_element(name) \
	rc = xmlTextWriterStartElement(writer, BAD_CAST name); \
	if (rc < 0) \
	{ \
		printf("Error at xmlTextWriterStartElement['%s'].\n", name); \
		return; \
	}

#define write_attribute(name, value) \
	rc = xmlTextWriterWriteAttribute(writer, BAD_CAST name, BAD_CAST value); \
	if (rc < 0) \
	{ \
		printf("Error at xmlTextWriterWriteAttribute['%s' -> '%s']\n", \
			name, value); \
		return; \
	}

#define format_element(name, value) \
	rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST name, "%s", value); \
	if (rc < 0) \
	{ \
		printf("Error at xmlTextWriterFormatElement['%s'].\n", name); \
		return; \
	}

#define write_base64(data, count) \
	rc = xmlTextWriterWriteBase64(writer, BAD_CAST data, 0, count); \
	if (rc < 0) \
	{ \
		printf("Error at xmlTextWriterWriteBase64['BinData']\n"); \
		return; \
	}

#define end_document() \
	rc = xmlTextWriterEndDocument(writer); \
	if (rc < 0) \
	{ \
		printf("Error at xmlTextWriterEndDocument.\n"); \
		return; \
	}

void
usage(int argc, char* argv[])
{
	printf("%s <output_filename>\n", argv[0]);
	exit(-1);
}


int
main(int argc, char* argv[])
{
	int rc;
	xmlTextWriterPtr writer;
	xmlChar *tmp;
	xmlDocPtr doc;
	const char* file;

	/* Check usage and assign out default filename. */
	if (argc != 2)
	{
		usage(argc, argv);
	}
	file = argv[1];

	/* Create a new XmlWrite for DOM, no compression. */
	writer = xmlNewTextWriterDoc(&doc, 0);
	if (writer == NULL)
	{
		printf("Error creating XML DOM writer.\n");
		return;
	}

	/* Start the document with the xml default for the version,
	 * encoding ISO 8859-1 and the default for the standalone
	 * declaration. */
	start_document();

	/* Start the OME element. Since this is the first element, this will
	 * be the root element of the document. */
	start_element("ome:OME");

	/* Add attributes to the OME element. */
	write_attribute("xmlns:bf", 
		"http://www.openmicroscopy.org/Schemas/BinaryFile/2008-09");
	write_attribute("xmlns:ome",
		"http://www.openmicroscopy.org/Schemas/OME/2008-09");
	write_attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
	write_attribute("xsi:schemaLocation",
		"http://www.openmicroscopy.org/Schemas/OME/2008-09 http://www.openmicroscopy.org/Schemas/OME/2008-09/ome.xsd");

	/* Start the Image element. */
	start_element("ome:Image");

	/* Add attributes to the Image element. */
	write_attribute("ID", "Image:1");
	write_attribute("Name", "Name92");
	write_attribute("DefaultPixels", "Pixels:1");

	/* Write the CreationDate element with CDATA. */
	format_element("ome:CreationDate", "2006-05-04T18:13:51.0Z");

	/* Start the Pixels element. */
	start_element("ome:Pixels");

	/* Add attributes to the Pixels element. */
	write_attribute("ID", "Pixels:1");
	write_attribute("DimensionOrder", "XYZCT");
	write_attribute("PixelType", "int8");
	write_attribute("BigEndian", "false");
	write_attribute("SizeX", "2");
	write_attribute("SizeY", "2");
	write_attribute("SizeZ", "2");
	write_attribute("SizeC", "2");
	write_attribute("SizeT", "2");

	/* Start the BinData element. */
	start_element("bf:BinData");

	/* Add attributes and Base64 CDATA to the BinData element. */
	write_attribute("Compression", "none");
	write_attribute("Length", "10");
	write_base64("default", 7);

	/* Close the Pixels, Image and OME elements using xmlTextWriterEndDocument
	 * instead of calling xmlTextWriterEndElement on each to save some work. */
	end_document();

	xmlFreeTextWriter(writer);
	xmlSaveFileEnc(file, doc, DEFAULT_ENCODING);
	xmlFreeDoc(doc);
}
