<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="text"/>
	<xsl:template match="/">
		<xsl:text><![CDATA[
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
]]>
</xsl:text>
		<xsl:call-template name="serializer"/>		
		<xsl:apply-templates select="tests/test"/>
		<xsl:text>
int main(int argc, char **argv) {
</xsl:text>
		<xsl:apply-templates select="tests/test" mode="call"/>
		<xsl:text>
	/* printf("finished.\n"); */
	return (0);
}
</xsl:text>
	</xsl:template>	
	<xsl:template match="tests/test" mode="call">
		<xsl:text>	nsTest_</xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>();
</xsl:text>
	</xsl:template>
	<xsl:template name="xml-text">
		<xsl:param name="text"/>
		<xsl:call-template name="replace-string">
			<!-- Substitute #10 for " -->	        			
	        <xsl:with-param name="from" select="'
'"/>
	        <xsl:with-param name="to" select="'"
"'"/>
			<xsl:with-param name="text">
				<xsl:call-template name="replace-string">
					<!-- Substitute " for \" -->
	        		<xsl:with-param name="from" select="'"'"/>
	        		<xsl:with-param name="to" select="'\"'"/>
					<xsl:with-param name="text">
						<xsl:call-template name="replace-string">
							<!-- Remove tabs. -->
			        		<xsl:with-param name="from" select="'	'"/>
			        		<xsl:with-param name="to" select="''"/>
							<xsl:with-param name="text" select="$text"/>
	    				</xsl:call-template>
					</xsl:with-param>
    			</xsl:call-template>
			</xsl:with-param>
    	</xsl:call-template>
		
	</xsl:template>
	<xsl:template match="doc" mode="define">
		<xsl:text>	xmlDocPtr </xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>;
</xsl:text>
		<xsl:text>	const char * </xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>_str = "</xsl:text>
		<xsl:call-template name="xml-text">
	        <xsl:with-param name="text" select="."/>
    	</xsl:call-template>		
		<xsl:text>";
</xsl:text>
	</xsl:template>
	<xsl:template match="expected" mode="define">
		<xsl:text>	const char * </xsl:text>	
		<xsl:text>exp_str = "</xsl:text>
		<xsl:call-template name="xml-text">
	        <xsl:with-param name="text" select="."/>
    	</xsl:call-template>		
		<xsl:text>";
</xsl:text>
	</xsl:template>
	<xsl:template match="doc">
		<xsl:text>	</xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text> = xmlReadDoc(BAD_CAST </xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>_str, NULL, NULL, 0);
</xsl:text>
			
		<xsl:apply-templates select="following-sibling::*[1]"/>
		<xsl:text>	xmlFreeDoc(</xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>);
</xsl:text>
	</xsl:template>
	<xsl:template match="xpath">
	</xsl:template>
	<xsl:template match="var" mode="define">
		<xsl:text>	xmlNodePtr </xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>;
</xsl:text>
	</xsl:template>
	<xsl:template match="var">
		<xsl:if test="xpath">
			<!-- Create XPath context. -->
			<xsl:text>	/* Selecting node "</xsl:text><xsl:value-of select="@name"/><xsl:text>". */
</xsl:text>
			<xsl:text>	xp = xmlXPathNewContext(</xsl:text>
			<xsl:value-of select="xpath/@doc"/>
			<xsl:text>);
</xsl:text>
			<!-- Register namespaces. -->
			<xsl:for-each select="xpath/reg-ns">
				<xsl:text>	xmlXPathRegisterNs(xp, BAD_CAST "</xsl:text>
				<xsl:value-of select="@prefix"/>
				<xsl:text>", BAD_CAST "</xsl:text>
				<xsl:value-of select="@ns"/>
				<xsl:text>");
</xsl:text>
			</xsl:for-each>
			<!-- Evaluate. -->
			<xsl:text>	</xsl:text>
			<xsl:value-of select="@name"/>
			<xsl:text> = nsSelectNode(xp, "</xsl:text>
			<xsl:value-of select="xpath/@select-node"/>
			<xsl:text>");
</xsl:text>
			<xsl:text>	xmlXPathFreeContext(xp);
</xsl:text>
		</xsl:if>
		<xsl:apply-templates select="following-sibling::*[1]"/>
	</xsl:template>
	<xsl:template match="reconcile-ns">
		<xsl:text>	/* Reconcile node "</xsl:text><xsl:value-of select="@ref"/><xsl:text>". */
</xsl:text>
		<xsl:text>	xmlDOMWrapReconcileNamespaces(NULL, </xsl:text>
		<xsl:value-of select="@node"/>
		<xsl:text>, 0);
</xsl:text>
		<xsl:apply-templates select="following-sibling::*[1]"/>
	</xsl:template>
	<xsl:template match="remove">
		<xsl:text>	xmlDOMWrapRemoveNode(NULL, </xsl:text>
		<xsl:value-of select="@node"/>
		<xsl:text>->doc, </xsl:text>
		<xsl:value-of select="@node"/>
		<xsl:text>, 0);
</xsl:text>
		<xsl:apply-templates select="following-sibling::*[1]"/>
	</xsl:template>
	<xsl:template match="adopt">
		<xsl:text>	/* Adopt "</xsl:text><xsl:value-of select="@node"/><xsl:text>". */
</xsl:text>
		<xsl:text>	xmlDOMWrapAdoptNode(NULL, </xsl:text>
		<xsl:value-of select="@node"/>
		<xsl:text>->doc, </xsl:text>
		<xsl:value-of select="@node"/>
		<xsl:text>, </xsl:text>
		<xsl:value-of select="@dest-doc"/>
		<xsl:text>, </xsl:text>
		<xsl:choose>
			<xsl:when test="@dest-parent">
				<xsl:value-of select="@dest-parent"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:text>NULL</xsl:text>
			</xsl:otherwise>
		</xsl:choose>		
		<xsl:text>, 0);
</xsl:text>
		<xsl:apply-templates select="following-sibling::*[1]"/>
	</xsl:template>
	<xsl:template match="append-child">
		<xsl:text>	xmlAddChild(</xsl:text>
		<xsl:value-of select="@parent"/>
		<xsl:text>, </xsl:text>
		<xsl:value-of select="@child"/>
		<xsl:text>);
</xsl:text>
		<xsl:apply-templates select="following-sibling::*[1]"/>
	</xsl:template>
	<xsl:template match="expected">		
		<xsl:text>	/* Serialize "</xsl:text><xsl:value-of select="@doc"/><xsl:text>". */
</xsl:text>
		<xsl:text>	result_str = nsSerializeNode(xmlDocGetRootElement(</xsl:text>
		<xsl:value-of select="@doc"/>
		<xsl:text>));
</xsl:text>
		<xsl:text>	/* Compare result. */
	if (! xmlStrEqual(BAD_CAST result_str, BAD_CAST exp_str)) {
		printf("FAILED\n");
		printf("%s\n", (const char *) result_str);
		printf("- - -\n");
		printf("Expected:\n%s\n", exp_str);
		printf("= = =\n");
	}
	xmlFree(result_str);
</xsl:text>
	</xsl:template>
	<!--********
	    * TEST *
	    ********-->
	<xsl:template match="test">		
		<xsl:text>void nsTest_</xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>(void) {
	xmlChar * result_str;
	xmlXPathContextPtr xp;
	int memory;
</xsl:text>
		<xsl:apply-templates select="*" mode="define"/>
		<xsl:text>
	memory = xmlMemUsed();
	xmlInitParser();

</xsl:text>
		<xsl:apply-templates select="child::*[1]"/>
		<xsl:text>
	xmlCleanupParser();
	memory = xmlMemUsed() - memory;
	if (memory != 0) {		
		printf("## '%s' MEMORY leak: %d\n", "</xsl:text>
		<xsl:value-of select="@name"/>
		<xsl:text>", memory);
    }		
}
</xsl:text>	
	</xsl:template>
	<xsl:template name="serializer">
		<xsl:text>
		
xmlChar * nsSerializeNode(xmlNodePtr node) {
	xmlChar * ret;
	xmlOutputBufferPtr buf;
	buf = xmlAllocOutputBuffer(NULL);
	xmlNodeDumpOutput(buf, node->doc, node, 0, 0, NULL);
	xmlOutputBufferFlush(buf);
	ret = (xmlChar *) buf->buffer->content;
	buf->buffer->content = NULL;
	(void) xmlOutputBufferClose(buf);
	return (ret);
}
xmlNodePtr nsSelectNode(xmlXPathContextPtr xp, const char * xpath) {
	xmlXPathObjectPtr xpres;
	xmlNodePtr ret;	
		
	xpres = xmlXPathEval(BAD_CAST xpath, xp);
	ret = xpres->nodesetval->nodeTab[0];
	xmlXPathFreeObject(xpres);
	return (ret);
}
</xsl:text>
	</xsl:template>
	<xsl:template name="replace-string">
    <xsl:param name="text"/>
    <xsl:param name="from"/>
    <xsl:param name="to"/>
    <xsl:choose>
      <xsl:when test="contains($text, $from)">
	<xsl:variable name="before" select="substring-before($text, $from)"/>
	<xsl:variable name="after" select="substring-after($text, $from)"/>
	<xsl:variable name="prefix" select="concat($before, $to)"/>
	<xsl:value-of select="$before"/>
	<xsl:value-of select="$to"/>
        <xsl:call-template name="replace-string">
	  <xsl:with-param name="text" select="$after"/>
	  <xsl:with-param name="from" select="$from"/>
	  <xsl:with-param name="to" select="$to"/>
	</xsl:call-template>
      </xsl:when> 
      <xsl:otherwise>
        <xsl:value-of select="$text"/>  
      </xsl:otherwise>
    </xsl:choose>            
 </xsl:template>
		
	
</xsl:stylesheet>