mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-08 11:02:18 +03:00
I generate a root node, I assume it's significant progress !
* libxslt/transform.[ch] Makefile.am: started adding the transformation module * pattern.[ch] xslt.c: more work... Daniel
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
|
Thu Jan 11 21:10:59 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
|
* libxslt/transform.[ch] Makefile.am: started adding the
|
||||||
|
transformation module
|
||||||
|
* pattern.[ch] xslt.c: more work...
|
||||||
|
|
||||||
Thu Jan 11 14:02:03 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
Thu Jan 11 14:02:03 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* libxslt/pattern.c: started adding xsltTestCompMatch()
|
* libxslt/pattern.c: started adding xsltTestCompMatch()
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ libxslt_la_SOURCES = \
|
|||||||
xslt.h \
|
xslt.h \
|
||||||
pattern.c \
|
pattern.c \
|
||||||
pattern.h \
|
pattern.h \
|
||||||
|
transform.c \
|
||||||
|
transform.h \
|
||||||
xsltInternals.h
|
xsltInternals.h
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ typedef xsltCompMatch *xsltCompMatchPtr;
|
|||||||
struct _xsltCompMatch {
|
struct _xsltCompMatch {
|
||||||
struct _xsltCompMatch *next; /* siblings in the name hash */
|
struct _xsltCompMatch *next; /* siblings in the name hash */
|
||||||
int priority; /* the priority */
|
int priority; /* the priority */
|
||||||
|
xsltTemplatePtr template; /* the associated template */
|
||||||
|
|
||||||
/* TODO fix the statically allocated size */
|
/* TODO fix the statically allocated size */
|
||||||
int nbStep;
|
int nbStep;
|
||||||
@@ -125,8 +126,18 @@ xsltNewCompMatch(void) {
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xsltFreeCompMatch(xsltCompMatchPtr comp) {
|
xsltFreeCompMatch(xsltCompMatchPtr comp) {
|
||||||
|
xsltStepOpPtr op;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (comp == NULL)
|
if (comp == NULL)
|
||||||
return;
|
return;
|
||||||
|
for (i = 0;i < comp->nbStep;i++) {
|
||||||
|
op = &comp->steps[i];
|
||||||
|
if (op->value != NULL)
|
||||||
|
xmlFree(op->value);
|
||||||
|
if (op->value2 != NULL)
|
||||||
|
xmlFree(op->value2);
|
||||||
|
}
|
||||||
memset(comp, -1, sizeof(xsltCompMatch));
|
memset(comp, -1, sizeof(xsltCompMatch));
|
||||||
xmlFree(comp);
|
xmlFree(comp);
|
||||||
}
|
}
|
||||||
@@ -680,6 +691,7 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) {
|
|||||||
pat = xsltCompilePattern(cur->match);
|
pat = xsltCompilePattern(cur->match);
|
||||||
if (pat == NULL)
|
if (pat == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
|
pat->template = cur;
|
||||||
if (cur->priority != XSLT_PAT_NO_PRIORITY)
|
if (cur->priority != XSLT_PAT_NO_PRIORITY)
|
||||||
pat->priority = cur->priority;
|
pat->priority = cur->priority;
|
||||||
|
|
||||||
@@ -746,14 +758,14 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) {
|
|||||||
*/
|
*/
|
||||||
if (list->priority <= pat->priority) {
|
if (list->priority <= pat->priority) {
|
||||||
pat->next = list;
|
pat->next = list;
|
||||||
xmlHashAddEntry(style->templatesHash, name, pat);
|
xmlHashUpdateEntry(style->templatesHash, name, pat, NULL);
|
||||||
#ifdef DEBUG_PARSING
|
#ifdef DEBUG_PARSING
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsltAddTemplate: added head hash for %s\n", name);
|
"xsltAddTemplate: added head hash for %s\n", name);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
while (list->next != NULL) {
|
while (list->next != NULL) {
|
||||||
if (list->next->priority < pat->priority)
|
if (list->next->priority <= pat->priority)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pat->next = list->next;
|
pat->next = list->next;
|
||||||
@@ -775,6 +787,83 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) {
|
|||||||
*/
|
*/
|
||||||
xsltTemplatePtr
|
xsltTemplatePtr
|
||||||
xsltGetTemplate(xsltStylesheetPtr style, xmlNodePtr node) {
|
xsltGetTemplate(xsltStylesheetPtr style, xmlNodePtr node) {
|
||||||
|
const xmlChar *name;
|
||||||
|
xsltCompMatchPtr list;
|
||||||
|
|
||||||
|
if ((style == NULL) || (node == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/* TODO : handle IDs/keys here ! */
|
||||||
|
if (style->templatesHash == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use a name as selector
|
||||||
|
*/
|
||||||
|
switch (node->type) {
|
||||||
|
case XML_ELEMENT_NODE:
|
||||||
|
case XML_ATTRIBUTE_NODE:
|
||||||
|
case XML_PI_NODE:
|
||||||
|
name = node->name;
|
||||||
|
break;
|
||||||
|
case XML_DOCUMENT_NODE:
|
||||||
|
case XML_HTML_DOCUMENT_NODE:
|
||||||
|
name = (const xmlChar *)"/";
|
||||||
|
break;
|
||||||
|
case XML_TEXT_NODE:
|
||||||
|
case XML_CDATA_SECTION_NODE:
|
||||||
|
case XML_ENTITY_REF_NODE:
|
||||||
|
case XML_ENTITY_NODE:
|
||||||
|
case XML_COMMENT_NODE:
|
||||||
|
case XML_DOCUMENT_TYPE_NODE:
|
||||||
|
case XML_DOCUMENT_FRAG_NODE:
|
||||||
|
case XML_NOTATION_NODE:
|
||||||
|
case XML_DTD_NODE:
|
||||||
|
case XML_ELEMENT_DECL:
|
||||||
|
case XML_ATTRIBUTE_DECL:
|
||||||
|
case XML_ENTITY_DECL:
|
||||||
|
case XML_NAMESPACE_DECL:
|
||||||
|
case XML_XINCLUDE_START:
|
||||||
|
case XML_XINCLUDE_END:
|
||||||
|
return(NULL);
|
||||||
|
default:
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (name == NULL)
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find the list of appliable expressions based on the name
|
||||||
|
*/
|
||||||
|
list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name);
|
||||||
|
if (list == NULL) {
|
||||||
|
#ifdef DEBUG_MATCHING
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltGetTemplate: empty set for %s\n", name);
|
||||||
|
#endif
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
while (list != NULL) {
|
||||||
|
if (xsltTestCompMatch(list, node))
|
||||||
|
return(list->template);
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeTemplateHashes:
|
||||||
|
* @style: an XSLT stylesheet
|
||||||
|
*
|
||||||
|
* Free up the memory used by xsltAddTemplate/xsltGetTemplate mechanism
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeTemplateHashes(xsltStylesheetPtr style) {
|
||||||
|
if (style->templatesHash != NULL)
|
||||||
|
xmlHashFree((xmlHashTablePtr) style->templatesHash,
|
||||||
|
(xmlHashDeallocator) xsltFreeCompMatchList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ int xsltAddTemplate (xsltStylesheetPtr style,
|
|||||||
xsltTemplatePtr cur);
|
xsltTemplatePtr cur);
|
||||||
xsltTemplatePtr xsltGetTemplate (xsltStylesheetPtr style,
|
xsltTemplatePtr xsltGetTemplate (xsltStylesheetPtr style,
|
||||||
xmlNodePtr node);
|
xmlNodePtr node);
|
||||||
|
void xsltFreeTemplateHashes (xsltStylesheetPtr style);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
187
libxslt/transform.c
Normal file
187
libxslt/transform.c
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* transform.c: Implemetation of the XSL Transformation 1.0 engine
|
||||||
|
* transform part, i.e. applying a Stylesheet to a document
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Daniel.Veillard@imag.fr
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xsltconfig.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/valid.h>
|
||||||
|
#include <libxml/hash.h>
|
||||||
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/HTMLtree.h>
|
||||||
|
#include "xslt.h"
|
||||||
|
#include "xsltInternals.h"
|
||||||
|
#include "pattern.h"
|
||||||
|
#include "transform.h"
|
||||||
|
|
||||||
|
#define DEBUG_PROCESS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To cleanup
|
||||||
|
*/
|
||||||
|
xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is no XSLT specific error reporting module yet
|
||||||
|
*/
|
||||||
|
#define xsltGenericError xmlGenericError
|
||||||
|
#define xsltGenericErrorContext xmlGenericErrorContext
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Useful macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TODO \
|
||||||
|
xsltGenericError(xsltGenericErrorContext, \
|
||||||
|
"Unimplemented block at %s:%d\n", \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
|
||||||
|
#define STRANGE \
|
||||||
|
xsltGenericError(xsltGenericErrorContext, \
|
||||||
|
"Internal error at %s:%d\n", \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types are private:
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum xsltOutputType {
|
||||||
|
XSLT_OUTPUT_XML = 0,
|
||||||
|
XSLT_OUTPUT_HTML,
|
||||||
|
XSLT_OUTPUT_TEXT
|
||||||
|
} xsltOutputType;
|
||||||
|
|
||||||
|
typedef struct _xsltTransformContext xsltTransformContext;
|
||||||
|
typedef xsltTransformContext *xsltTransformContextPtr;
|
||||||
|
struct _xsltTransformContext {
|
||||||
|
xsltOutputType type; /* the type of output */
|
||||||
|
xmlNodePtr node; /* the current node */
|
||||||
|
xmlNodeSetPtr nodeList; /* the current node list */
|
||||||
|
|
||||||
|
xmlNodePtr output; /* output node */
|
||||||
|
|
||||||
|
xmlXPathContextPtr xpathCtxt; /* the XPath context */
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
*
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltNewTransformContext:
|
||||||
|
*
|
||||||
|
* Create a new XSLT TransformContext
|
||||||
|
*
|
||||||
|
* Returns the newly allocated xsltTransformContextPtr or NULL in case of error
|
||||||
|
*/
|
||||||
|
xsltTransformContextPtr
|
||||||
|
xsltNewTransformContext(void) {
|
||||||
|
xsltTransformContextPtr cur;
|
||||||
|
|
||||||
|
cur = (xsltTransformContextPtr) xmlMalloc(sizeof(xsltTransformContext));
|
||||||
|
if (cur == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltNewTransformContext : malloc failed\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(cur, 0, sizeof(xsltTransformContext));
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFreeTransformContext:
|
||||||
|
* @ctxt: an XSLT parser context
|
||||||
|
*
|
||||||
|
* Free up the memory allocated by @ctxt
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
|
||||||
|
if (ctxt == NULL)
|
||||||
|
return;
|
||||||
|
memset(ctxt, -1, sizeof(xsltTransformContext));
|
||||||
|
xmlFree(ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
*
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltApplyStylesheet:
|
||||||
|
* @style: a parsed XSLT stylesheet
|
||||||
|
* @doc: a parsed XML document
|
||||||
|
*
|
||||||
|
* Apply the stylesheet to the document
|
||||||
|
* NOTE: This may lead to a non-wellformed output XML wise !
|
||||||
|
*
|
||||||
|
* Returns the result document or NULL in case of error
|
||||||
|
*/
|
||||||
|
xmlDocPtr
|
||||||
|
xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) {
|
||||||
|
xmlDocPtr res = NULL;
|
||||||
|
xsltTransformContextPtr ctxt = NULL;
|
||||||
|
|
||||||
|
if ((style == NULL) || (doc == NULL))
|
||||||
|
return(NULL);
|
||||||
|
ctxt = xsltNewTransformContext();
|
||||||
|
if (ctxt == NULL)
|
||||||
|
return(NULL);
|
||||||
|
if ((style->method != NULL) &&
|
||||||
|
(!xmlStrEqual(style->method, (const xmlChar *) "xml"))) {
|
||||||
|
if (xmlStrEqual(style->method, (const xmlChar *) "html")) {
|
||||||
|
ctxt->type = XSLT_OUTPUT_HTML;
|
||||||
|
res = htmlNewDoc(style->doctypePublic, style->doctypeSystem);
|
||||||
|
if (res == NULL)
|
||||||
|
goto error;
|
||||||
|
} else if (xmlStrEqual(style->method, (const xmlChar *) "text")) {
|
||||||
|
ctxt->type = XSLT_OUTPUT_TEXT;
|
||||||
|
TODO
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsltApplyStylesheet: insupported method %s\n",
|
||||||
|
style->method);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctxt->type = XSLT_OUTPUT_XML;
|
||||||
|
res = xmlNewDoc(style->version);
|
||||||
|
if (res == NULL)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (style->encoding != NULL)
|
||||||
|
doc->encoding = xmlStrdup(style->encoding);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
res->intSubset = xmlCreateIntSubset(
|
||||||
|
*/
|
||||||
|
|
||||||
|
xsltFreeTransformContext(ctxt);
|
||||||
|
return(res);
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (res != NULL)
|
||||||
|
xmlFreeDoc(res);
|
||||||
|
if (ctxt != NULL)
|
||||||
|
xsltFreeTransformContext(ctxt);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
30
libxslt/transform.h
Normal file
30
libxslt/transform.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* transform.h: Interfaces, constants and types related to the XSLT engine
|
||||||
|
* transform part.
|
||||||
|
*
|
||||||
|
* See Copyright for the status of this software.
|
||||||
|
*
|
||||||
|
* Daniel.Veillard@imag.fr
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XML_XSLT_TRANSFORM_H__
|
||||||
|
#define __XML_XSLT_TRANSFORM_H__
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interfaces
|
||||||
|
*/
|
||||||
|
xmlDocPtr xsltApplyStylesheet (xsltStylesheetPtr style,
|
||||||
|
xmlDocPtr doc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __XML_XSLT_TRANSFORM_H__ */
|
||||||
|
|
||||||
@@ -123,6 +123,11 @@ void
|
|||||||
xsltFreeTemplate(xsltTemplatePtr template) {
|
xsltFreeTemplate(xsltTemplatePtr template) {
|
||||||
if (template == NULL)
|
if (template == NULL)
|
||||||
return;
|
return;
|
||||||
|
if (template->match) xmlFree(template->match);
|
||||||
|
if (template->name) xmlFree(template->name);
|
||||||
|
if (template->nameURI) xmlFree(template->nameURI);
|
||||||
|
if (template->mode) xmlFree(template->mode);
|
||||||
|
if (template->modeURI) xmlFree(template->modeURI);
|
||||||
memset(template, -1, sizeof(xsltTemplate));
|
memset(template, -1, sizeof(xsltTemplate));
|
||||||
xmlFree(template);
|
xmlFree(template);
|
||||||
}
|
}
|
||||||
@@ -178,6 +183,8 @@ void
|
|||||||
xsltFreeStylesheet(xsltStylesheetPtr sheet) {
|
xsltFreeStylesheet(xsltStylesheetPtr sheet) {
|
||||||
if (sheet == NULL)
|
if (sheet == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
xsltFreeTemplateHashes(sheet);
|
||||||
xsltFreeTemplateList(sheet->templates);
|
xsltFreeTemplateList(sheet->templates);
|
||||||
if (sheet->doc != NULL)
|
if (sheet->doc != NULL)
|
||||||
xmlFreeDoc(sheet->doc);
|
xmlFreeDoc(sheet->doc);
|
||||||
|
|||||||
@@ -7,9 +7,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <libxml/xmlversion.h>
|
||||||
#include <libxml/xmlmemory.h>
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/debugXML.h>
|
||||||
#include <libxslt/xslt.h>
|
#include <libxslt/xslt.h>
|
||||||
#include <libxslt/xsltInternals.h>
|
#include <libxslt/xsltInternals.h>
|
||||||
|
#include <libxslt/transform.h>
|
||||||
|
|
||||||
static int debug = 0;
|
static int debug = 0;
|
||||||
|
|
||||||
@@ -17,6 +20,7 @@ int
|
|||||||
main(int argc, char **argv) {
|
main(int argc, char **argv) {
|
||||||
int i;
|
int i;
|
||||||
xsltStylesheetPtr cur;
|
xsltStylesheetPtr cur;
|
||||||
|
xmlDocPtr doc, res;
|
||||||
|
|
||||||
LIBXML_TEST_VERSION
|
LIBXML_TEST_VERSION
|
||||||
for (i = 1; i < argc ; i++) {
|
for (i = 1; i < argc ; i++) {
|
||||||
@@ -26,11 +30,34 @@ main(int argc, char **argv) {
|
|||||||
xmlSubstituteEntitiesDefault(1);
|
xmlSubstituteEntitiesDefault(1);
|
||||||
for (i = 1; i < argc ; i++) {
|
for (i = 1; i < argc ; i++) {
|
||||||
if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
|
if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
|
||||||
cur = xsltParseStylesheetFile(argv[i]);
|
cur = xsltParseStylesheetFile((const xmlChar *)argv[i]);
|
||||||
xsltFreeStylesheet(cur);
|
i++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (;i < argc ; i++) {
|
||||||
|
doc = xmlParseFile(argv[i]);
|
||||||
|
if (doc == NULL) {
|
||||||
|
fprintf(stderr, "unable to parse %s\n", argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res = xsltApplyStylesheet(cur, doc);
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
if (res == NULL) {
|
||||||
|
fprintf(stderr, "no result for %s\n", argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#ifdef LIBXML_DEBUG_ENABLED
|
||||||
|
if (debug)
|
||||||
|
xmlDebugDumpDocument(stdout, res);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
xmlDocDump(stdout, res);
|
||||||
|
|
||||||
|
xmlFreeDoc(res);
|
||||||
|
}
|
||||||
|
if (cur != NULL)
|
||||||
|
xsltFreeStylesheet(cur);
|
||||||
xmlCleanupParser();
|
xmlCleanupParser();
|
||||||
xmlMemoryDump();
|
xmlMemoryDump();
|
||||||
return(0);
|
return(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user