* NEW: Added a new Document property to XMLExplorer.
* NEW: Added the Name and Value properties to XMLReader.Node.Attributes and
  XMLNode.Attributes, to get the name and value of the enumerated attribute.
* BUG: Fixed the XMLNode.Attributes enumeration.
* BUG: Fixed XMLExplorer taking the document itself as a node.
* OPT: Rewrote internal exception handling.

[GB.XML.XSLT]
* NEW: Added a new method XSLT.TransformToString() that returns a string 
  instead of an XML document.
* BUG: Fixed internal error management.

git-svn-id: svn://localhost/gambas/trunk@6416 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Adrien Prokopowicz 2014-08-05 02:02:56 +00:00
parent 3dbf3ca320
commit c41939ed3b
16 changed files with 327 additions and 248 deletions

View file

@ -74,7 +74,7 @@ try
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
GB.ReturnNull();
}
@ -94,7 +94,7 @@ try
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
}
END_METHOD
@ -128,7 +128,7 @@ else
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
}
}
@ -155,7 +155,7 @@ try
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
}
END_METHOD

View file

@ -139,7 +139,7 @@ try
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
}
END_METHOD
@ -253,7 +253,7 @@ try
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
}
GB.ReturnObject(array);

View file

@ -87,7 +87,7 @@ try
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
}
@ -105,12 +105,25 @@ GB.ReturnInteger(THIS->state);
END_PROPERTY
BEGIN_METHOD(CExplorer_document, GB_OBJECT doc)
BEGIN_METHOD(CExplorer_load, GB_OBJECT doc)
THIS->Load((Document*)(VARGOBJ(CDocument, doc)->node));
END_METHOD
BEGIN_PROPERTY(CExplorer_document)
if(READ_PROPERTY)
{
XML_ReturnNode(THIS->loadedDocument);
}
else
{
THIS->Load((Document*)(VPROPOBJ(CDocument)->node));
}
END_PROPERTY
GB_DESC CExplorerReadFlagsDesc[] =
{
GB_DECLARE(".XmlExplorerReadFlags", 0), GB_VIRTUAL_CLASS(),
@ -127,7 +140,8 @@ GB_DESC CExplorerDesc[] =
GB_METHOD("_new", "", CExplorer_new, "[(Document)XmlDocument]"),
GB_METHOD("_free", "", CExplorer_free, ""),
GB_METHOD("Load", "", CExplorer_document, "(Document)XmlDocument"),
GB_METHOD("Load", "", CExplorer_load, "(Document)XmlDocument"),
GB_PROPERTY("Document", "XMLDocument", CExplorer_document),
GB_PROPERTY_SELF("ReadFlags", ".XmlExplorerReadFlags"),
GB_PROPERTY_READ("Node", "XmlNode", CExplorer_Node),
GB_PROPERTY_READ("Eof", "b", CExplorer_eof),

View file

@ -27,6 +27,7 @@
#include "serializer.h"
#include <stdlib.h>
#define THISOBJ ((CNode*)_object)
#define THIS (static_cast<CNode*>(_object)->node)
#define NODE_BASE 0
@ -35,8 +36,10 @@
#define NODE_COMMENT 3
#define NODE_CDATA 4
#define NODE_ATTRIBUTE 5
#define NODE_DOCUMENT 6
BEGIN_METHOD_VOID(CNode_new)
if(XMLNode_NoInstanciate()) return;
@ -253,13 +256,43 @@ else
*reinterpret_cast<Attribute**>(GB.GetEnum()) = attr;
}
THISOBJ->curAttrEnum = attr;
if(attr == 0) {GB.StopEnum(); return;}
XML_ReturnNode(attr);
END_METHOD
BEGIN_PROPERTY(CElementAttributes_name)
if(!THISOBJ->curAttrEnum)
{
GB.Error("No enumerated attribute available");
GB.ReturnNull();
return;
}
GB.ReturnNewString(THISOBJ->curAttrEnum->attrName, THISOBJ->curAttrEnum->lenAttrName);
END_PROPERTY
BEGIN_PROPERTY(CElementAttributes_value)
if(!THISOBJ->curAttrEnum)
{
GB.Error("No enumerated attribute available");
GB.ReturnNull();
return;
}
GB.ReturnNewString(THISOBJ->curAttrEnum->attrValue, THISOBJ->curAttrEnum->lenAttrValue);
END_PROPERTY
BEGIN_PROPERTY(CNode_childNodes)
GB_ARRAY array;
@ -341,6 +374,8 @@ GB_DESC CElementAttributesDesc[] =
GB_METHOD("_put", "s", CElementAttributes_put, "(Value)s(Name)s"),
GB_METHOD("_next", "XmlNode", CElementAttributes_next, ""),
GB_PROPERTY_READ("Count", "i", CElementAttributes_count),
GB_PROPERTY_READ("Name", "s", CElementAttributes_name),
GB_PROPERTY_READ("Value", "s", CElementAttributes_value),
GB_END_DECLARE
};

View file

@ -49,7 +49,7 @@ try
}
catch(XMLParseException &e)
{
GB.Error(e.what());
GB.Error(e.errorWhat);
}
END_METHOD
@ -144,18 +144,6 @@ GB.ReturnNewString(attr->attrValue, attr->lenAttrValue);
END_METHOD
/*BEGIN_METHOD(CReaderNodeAttr_put, GB_STRING value; GB_STRING name)
if(!THIS->foundNode)
{
return;
}
if(!THIS->foundNode->isElement()) return;
THIS->foundNode->toElement()->setAttribute(STRING(name), LENGTH(name),
STRING(value), LENGTH(value));
END_METHOD*/
BEGIN_PROPERTY(CReaderNodeAttr_count)
if(!THIS->foundNode || THIS->state == READ_END_CUR_ELEMENT)
@ -175,6 +163,32 @@ GB.ReturnInteger(0);
END_PROPERTY
BEGIN_PROPERTY(CReaderNodeAttr_name)
if(!THIS->curAttrEnum)
{
GB.Error("No enumerated attribute available");
GB.ReturnNull();
return;
}
GB.ReturnNewString(THIS->curAttrEnum->attrName, THIS->curAttrEnum->lenAttrName);
END_PROPERTY
BEGIN_PROPERTY(CReaderNodeAttr_value)
if(!THIS->curAttrEnum)
{
GB.Error("No enumerated attribute available");
GB.ReturnNull();
return;
}
GB.ReturnNewString(THIS->curAttrEnum->attrValue, THIS->curAttrEnum->lenAttrValue);
END_PROPERTY
BEGIN_METHOD(CReaderReadFlags_get, GB_INTEGER flag)
int flag = VARG(flag);
@ -193,34 +207,6 @@ END_METHOD
BEGIN_PROPERTY(CReaderNode_type)
/*if(!THIS->foundNode)
{
GB.ReturnInteger(0);
return;
}
if(THIS->curAttrEnum)
{
GB.ReturnInteger(READ_ATTRIBUTE);
return;
}
switch(THIS->foundNode->getType())
{
case Node::ElementNode:
GB.ReturnInteger(NODE_ELEMENT);break;
case Node::Comment:
GB.ReturnInteger(NODE_COMMENT);break;
case Node::NodeText:
GB.ReturnInteger(NODE_TEXT);break;
case Node::CDATA:
GB.ReturnInteger(NODE_CDATA);break;
default:
GB.ReturnInteger(0);
}
*/
GB.ReturnInteger(THIS->state);
END_PROPERTY
@ -299,10 +285,6 @@ BEGIN_PROPERTY(CReader_storedNodes)
if(!READ_PROPERTY) return;
//GBI::ObjectArray<Node> *nodes = new GBI::ObjectArray<Node>("XmlNode", *(THIS->storedElements));
//GB.ReturnObject(nodes->array);
//delete nodes;
GB.ReturnObject(0);
END_PROPERTY
@ -369,9 +351,10 @@ GB_DESC CReaderNodeAttributesDesc[] =
GB_DECLARE(".XmlReader.Node.Attributes", 0), GB_VIRTUAL_CLASS(),
GB_METHOD("_get", "s", CReaderNodeAttr_get, "(Name)s"),
//GB_METHOD("_put", "s", CReaderNodeAttr_put, "(Value)s(Name)s"),
GB_METHOD("_next", "s", CReaderNodeAttr_next, ""),
GB_PROPERTY_READ("Count", "i", CReaderNodeAttr_count),
GB_PROPERTY_READ("Name", "i", CReaderNodeAttr_name),
GB_PROPERTY_READ("Value", "i", CReaderNodeAttr_value),
GB_END_DECLARE
};

View file

@ -166,7 +166,7 @@ void XMLDocument_SetContent(Document *doc, const char *content, size_t len) thro
{
if(doc->docType == XMLDocumentType)//Strict document
{
throw XMLParseException("Extra root element", 0, 0, 0);
throw XMLParseException_New("Extra root element", 0, 0, 0);
}
}
@ -178,50 +178,9 @@ void XMLDocument_SetContent(Document *doc, const char *content, size_t len) thro
free(elements);
if(newRoot) doc->root = (Element*)newRoot;
/*if(!newRoot)
{
throw XMLParseException("No valid element root found", 0, 0, 0);
}*/
//this->setRoot(newRoot);
//if(!root) throw HTMLParseException(0, 0, "somewhere", "No valid root element found.");
}
/*
void Document::toString(char **output, size_t *len, int indent)
{
//<?xml version="1.0" encoding="UTF-8"?> //Len = 38
*len = 38 + (indent >= 0 ? 1 : 0); root->addStringLen(len, indent);
*output = (char*)malloc(*len);
memcpy(*output, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", 38);
*output += 38;
if(indent >= 0)
{
**output = SCHAR_N;
++(*output);
}
root->addString(output, indent);
(*output) -= (*len);
}
void Document::toGBString(char **output, size_t *len, int indent)
{
//<?xml version="1.0" encoding="UTF-8"?> //Len = 38
*len = 38 + (indent >= 0 ? 1 : 0); root->addStringLen(len, indent);
*output = GB.TempString(0, *len);
memcpy(*output, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", 38);
*output += 38;
if(indent >= 0)
{
**output = SCHAR_N;
++(*output);
}
root->addString(output, indent);
(*output) -= (*len);
}*/
void XMLDocument_Save(Document *doc, const char *fileName, bool indent)
{

View file

@ -55,9 +55,10 @@ void Explorer::Init()
void Explorer::Load(Document *doc)
{
//UNREF(loadedDocument);
Clear();
loadedDocument = doc;
CNode *obj = XMLNode_GetGBObject(loadedDocument);
GB.Ref(obj);
//GB.Ref(doc);
Read();
@ -66,7 +67,11 @@ void Explorer::Load(Document *doc)
void Explorer::Clear()
{
if(loadedDocument) XMLNode_DestroyParent((Node*)loadedDocument);
if(loadedDocument)
{
CNode *obj = XMLNode_GetGBObject(loadedDocument);
GB.Unref(POINTER(&obj));
}
loadedDocument = 0;
curNode = 0;
this->eof = false;
@ -104,7 +109,7 @@ int Explorer::MoveNext()
return nextNode->type;
}
//si plus d'enfants ni de frère, on remonte
else if(curNode->parent && curNode != loadedDocument->root)
else if(curNode->parent && curNode != loadedDocument->root && curNode->parent != loadedDocument)
{
curNode = curNode->parent;
endElement = true;

View file

@ -21,6 +21,7 @@ using namespace std;
#define DEBUG std::cerr << "XMLDBG (" << __FILE__ << ":" <<__LINE__ << ") :"
#define DEBUGH DEBUG << endl
#endif
typedef struct Node
@ -98,6 +99,17 @@ typedef TextNode CommentNode;
typedef TextNode CDATANode;
typedef struct XMLParseException
{
char *near;
size_t lenNear;
size_t line;
size_t column;
char *errorWhat;
}XMLParseException;
//Gambas XML component interface
#define XML_INTERFACE_VERSION 1

View file

@ -13,11 +13,13 @@ extern "C" GB_INTERFACE GB;
struct Node;
struct Attribute;
typedef struct CNode
{
GB_BASE ob;
Node *node;
Attribute *curAttrEnum;
}CNode;
typedef CNode CDocument;

View file

@ -95,6 +95,9 @@ void XMLNode_NewGBObject(Node *node)
case Node::DocumentNode:
node->GBObject = (CNode*)GB.New(GB.FindClass("XmlDocument"), 0, 0);
break;
case Node::AttributeNode:
node->GBObject = (CNode*)GB.New(GB.FindClass("XmlNode"), 0, 0);
break;
default:
fprintf(stderr, "FATAL : tried to create a Gambas object with invalid type.");
exit(EXIT_FAILURE);

View file

@ -129,21 +129,21 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
if(!curElement)//Pas d'élément courant
{
//ERREUR : CLOSING TAG WHEREAS NONE IS OPEN
throw(XMLParseException("Closing tag whereas none is open",
throw(XMLParseException_New("Closing tag whereas none is open",
data, lendata, pos - 1));
}
if((endData) < pos + curElement->lenTagName)//Impossible que les tags correspondent
{
//ERREUR : TAG MISMATCH
throw(XMLParseException("Tag mismatch",
throw(XMLParseException_New("Tag mismatch",
data, lendata, pos - 1));
}
//Les tags ne correspondent pas
else if(memcmp(pos, curElement->tagName, curElement->lenTagName) != 0)
{
//ERREUR : TAG MISMATCH
throw(XMLParseException("Tag mismatch",
throw(XMLParseException_New("Tag mismatch",
data, lendata, pos - 1));
}
else//Les tags correspondent, on remonte
@ -165,7 +165,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
if(!tag)//Commentaire sans fin
{
//ERREUR : NEVER-ENDING COMMENT
throw(XMLParseException("Never-ending comment",
throw(XMLParseException_New("Never-ending comment",
data, lendata, pos - 1));
}
@ -182,7 +182,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
if(!tag)//Cdata sans fin
{
//ERREUR : UNENDED CDATA
throw(XMLParseException("Never-ending CDATA",
throw(XMLParseException_New("Never-ending CDATA",
data, lendata, pos - 1));
}
@ -198,7 +198,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
tag = (char*)memchr(pos, '>', endData - pos);
if(!tag)//Doctype sans fin
{
throw(XMLParseException("Never-ending DOCTYPE",
throw(XMLParseException_New("Never-ending DOCTYPE",
data, lendata, pos - 1));
}
@ -208,7 +208,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
else// ... ?
{
//ERREUR : INVALID TAG
throw(XMLParseException("Invalid Tag",
throw(XMLParseException_New("Invalid Tag",
data, lendata, pos - 1));
}
}
@ -217,7 +217,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
tag = (char*)memchrs(pos, endData - pos, "?>", 2);//Looking for the end of the PI
if(!tag)//Endless PI
{
throw(XMLParseException("Never-ending Processing instruction",
throw(XMLParseException_New("Never-ending Processing instruction",
data, lendata, pos - 1));
}
@ -228,7 +228,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
else// ... ?
{
//ERREUR : INVALID TAG
throw(XMLParseException("Invalid Tag",
throw(XMLParseException_New("Invalid Tag",
data, lendata, pos - 1));
}
}//Si tout va bien, on a un nouvel élément
@ -239,7 +239,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
if(pos > endData)
{
//ERREUR : NEVER-ENDING TAG
throw(XMLParseException("Never-ending tag",
throw(XMLParseException_New("Never-ending tag",
data, lendata, pos - 1));
}
}
@ -282,7 +282,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
else
{
//ERREUR : INVALID TAG
throw(XMLParseException("Invalid tag",
throw(XMLParseException_New("Invalid tag",
data, lendata, pos - 1));
}
}
@ -295,7 +295,7 @@ Node** parseXML(char const *data, const size_t lendata, size_t *nodeCount) throw
if(delimiter != '"' && delimiter != '\'')
{
//ERREUR : EXPECTED ATTRIBUTE DELIMITER
throw(XMLParseException("Expected attribute delimiter",
throw(XMLParseException_New("Expected attribute delimiter",
data, lendata, pos - 1));
}
pos++;

View file

@ -142,7 +142,7 @@ int Reader::ReadChar(char car)
{
if(inTag)//Si on est déjà dans un tag
{
throw XMLParseException("Invalid tag Name", pos);
throw XMLParseException_New("Invalid tag Name", pos);
}
inNewTag = true;
inTagName = true;

View file

@ -280,14 +280,47 @@ void XML_Format(GB_VALUE *value, char* &dst, size_t &lenDst)
/************************************ Error Management ************************************/
void XMLParseException_AnalyzeText(XMLParseException *ex, const char *text, const size_t lenText, const char *posFailed) throw();
void ThrowXMLParseException(const char* nerror, const char *text, const size_t lenText, const char *posFailed)
{
throw XMLParseException(nerror, text, lenText, posFailed);
throw XMLParseException_New(nerror, text, lenText, posFailed);
}
XMLParseException::XMLParseException(const char *nerror, const char *data, const size_t lenData, const char *posFailed) throw()
: near(0), error(0), lenError(0), lenNear(0), line(1), column(1)
XMLParseException* XMLParseException_New()//Void initializer
{
XMLParseException *exception = new XMLParseException;
memset(exception, 0, sizeof(XMLParseException));
exception->line = 1;
exception->column = 1;
return exception;
}
XMLParseException* XMLParseException_New(const char *nerror, size_t posFailed)
{
XMLParseException *exception = XMLParseException_New();
size_t lenError;
char *error;
lenError = strlen(nerror) + 1;
error = (char*) malloc(lenError);
memcpy(error, nerror, lenError);
exception->errorWhat = (char*)malloc(37 + lenError);
sprintf(exception->errorWhat, "Parse error : %s !\n Position %zu", error, (size_t)posFailed);
exception->errorWhat[36 + lenError] = 0;
free(error);
return exception;
}
XMLParseException* XMLParseException_New(const char *nerror, const char *data, const size_t lenData, const char *posFailed) throw()
{
XMLParseException *exception = XMLParseException_New();
size_t lenError;
char *error;
lenError = strlen(nerror) + 1;
error = (char*) malloc(lenError);
memcpy(error, nerror, lenError);
@ -296,76 +329,63 @@ XMLParseException::XMLParseException(const char *nerror, const char *data, const
if(posFailed == 0)
{
errorWhat = (char*)malloc(17 + lenError);
sprintf(errorWhat, "Parse error : %s !", error);
errorWhat[16 + lenError] = 0;
return;
exception->errorWhat = (char*)malloc(17 + lenError);
sprintf(exception->errorWhat, "Parse error : %s !", error);
exception->errorWhat[16 + lenError] = 0;
return exception;
}
else if(!data || !lenData)
{
errorWhat = (char*)malloc(37 + lenError);
sprintf(errorWhat, "Parse error : %s !\n Position %zu", error, (size_t)posFailed);
errorWhat[36 + lenError] = 0;
return;
exception->errorWhat = (char*)malloc(37 + lenError);
sprintf(exception->errorWhat, "Parse error : %s !\n Position %zu", error, (size_t)posFailed);
exception->errorWhat[36 + lenError] = 0;
return exception;
}
if(posFailed > data + lenData || posFailed < data) return;
AnalyzeText(data, lenData, posFailed);
if(posFailed > data + lenData || posFailed < data) return exception;
XMLParseException_AnalyzeText(exception, data, lenData, posFailed);
errorWhat = (char*)malloc(61 + lenError + lenNear);
memset(errorWhat, 0, 61 + lenError + lenNear);
sprintf(errorWhat, "Parse error : %s !\n Line %zu , Column %zu : \n %s", error, line, column, near);
errorWhat[60 + lenError + lenNear] = 0;
exception->errorWhat = (char*)malloc(61 + lenError + exception->lenNear);
memset(exception->errorWhat, 0, 61 + lenError + exception->lenNear);
sprintf(exception->errorWhat, "Parse error : %s !\n Line %zu , Column %zu : \n %s", error, exception->line, exception->column, exception->near);
exception->errorWhat[60 + lenError + exception->lenNear] = 0;
return exception;
}
XMLParseException::XMLParseException(const char *nerror, size_t posFailed) throw()
: near(0), error(0), lenError(0), lenNear(0), line(1), column(1)
void XMLParseException_Free(XMLParseException* &ex) throw()
{
lenError = strlen(nerror) + 1;
error = (char*) malloc(lenError);
memcpy(error, nerror, lenError);
//Parse error : (errorText) !\n Line 123456789 , Column 123456789 : \n (near)
errorWhat = (char*)malloc(37 + lenError);
sprintf(errorWhat, "Parse error : %s !\n Position %zu", error, posFailed);
errorWhat[36 + lenError] = 0;
if(ex->near) free(ex->near);
free(ex);
ex = 0;
}
XMLParseException::~XMLParseException() throw()
{
if(near) free(near);
if(error) free(error);
}
void XMLParseException::AnalyzeText(const char *text, const size_t lenText, const char *posFailed) throw()
void XMLParseException_AnalyzeText(XMLParseException *ex, const char *text, const size_t lenText, const char *posFailed) throw()
{
for(const char *pos = text; pos < posFailed; ++pos)
{
++column;
++ex->column;
if(*pos == '\n')
{
column = 1;
++line;
ex->column = 1;
++ex->line;
}
else if(*pos == '\r')
{
if(*(pos + 1) == '\n') ++pos;
column = 1;
++line;
ex->column = 1;
++ex->line;
}
}
lenNear = text + lenText <= posFailed + 20 ? text + lenText - posFailed : 20;
if(lenNear == 0) return;
near = (char*)malloc(lenNear + 1);
memcpy(near, posFailed, lenNear);
near[lenNear] = 0;
}
const char* XMLParseException::what() const throw()
{
return errorWhat;
ex->lenNear = text + lenText <= posFailed + 20 ? text + lenText - posFailed : 20;
if(ex->lenNear == 0) return;
ex->near = (char*)malloc(ex->lenNear + 1);
memcpy(ex->near, posFailed, ex->lenNear);
ex->near[ex->lenNear] = 0;
}

View file

@ -46,30 +46,10 @@ void insertString(char *&src, size_t &lenSrc, const char *insert, size_t lenInse
bool GB_MatchString(const char *str, size_t lenStr, const char *pattern, size_t lenPattern, int mode = GB_STRCOMP_BINARY);
XMLParseException* XMLParseException_New(const char *nerror, size_t posFailed);
XMLParseException* XMLParseException_New(const char *nerror, const char *data, const size_t lenData, const char *posFailed) throw();
void ThrowXMLParseException(const char* nerror, const char *text, const size_t lenText, const char *posFailed);
class XMLParseException
{
public:
XMLParseException(const char* nerror, const char *text, const size_t lenText, const char *posFailed) throw();
XMLParseException(const char* nerror, size_t posFailed) throw();
virtual ~XMLParseException() throw();
virtual const char* what() const throw();
private:
void AnalyzeText(const char *text, const size_t lenText, const char *posFailed) throw();
char *near;
char *error;
size_t lenError;
size_t lenNear;
size_t line;
size_t column;
char *errorWhat;
};
#endif // UTILS_H

View file

@ -21,18 +21,73 @@
MA 02110-1301, USA.
***************************************************************************/
#define __CXSLT_C
#include "../gb.xml.h"
#include "../gbinterface.h"
#include "CXSLT.h"
extern GB_INTERFACE GB;
extern XML_INTERFACE XML;
#include <iostream>
#include <memory.h>
#include <libxml2/libxml/xinclude.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
void XSLT_Transform(Document* doc, Document* stylesheet,char* &outDocument, size_t &outDocumentLen) throw(XSLTException)
{
if(!doc->childCount) throw XSLTException("Void document");
if(!stylesheet->childCount) throw XSLTException("Void style sheet");
xsltStylesheetPtr sheet = 0;
char *StyleSheetOutput = NULL;
size_t StyleSheetLen = 0;
XML.SerializeXMLNode((Node*)stylesheet, StyleSheetOutput, StyleSheetLen, -1);
StyleSheetOutput =(char*)realloc(StyleSheetOutput, StyleSheetLen + 1);
StyleSheetOutput[StyleSheetLen] = 0;
xmlDoc *xmlStyleSheet = xmlParseDoc((xmlChar*)(StyleSheetOutput));
free(StyleSheetOutput);
if(!(sheet=xsltParseStylesheetDoc(xmlStyleSheet))) throw XSLTException("Invalid style sheet");
char *DocumentOutput;
size_t DocumentLen;
XML.SerializeXMLNode((Node*)doc, DocumentOutput, DocumentLen, -1);
DocumentOutput =(char*)realloc(DocumentOutput, DocumentLen + 1);
DocumentOutput[DocumentLen] = 0;
xmlDoc *xmlInputDoc = xmlParseDoc((xmlChar*)(DocumentOutput));
if(!xmlInputDoc) throw XSLTException("Unable to parse input document");
free(DocumentOutput);
xmlDoc *xmlOutDoc;
xmlOutDoc = xsltApplyStylesheet(sheet, xmlInputDoc, NULL);
if (!xmlOutDoc) throw XSLTException("Unable to apply style sheet");
int size;
xmlDocDumpFormatMemoryEnc(xmlOutDoc ,(xmlChar**)&outDocument, &size, "UTF-8", 1);
outDocumentLen = size;
xsltFreeStylesheet(sheet);
xmlFreeDoc(xmlOutDoc);
xmlFreeDoc(xmlInputDoc);
}
BEGIN_METHOD(CXSLT_Transform,GB_OBJECT inputDoc;GB_OBJECT inputStyleSheet)
if (GB.CheckObject(VARGOBJ(CDocument,inputDoc))) return;
@ -41,78 +96,67 @@ if (GB.CheckObject(VARGOBJ(CDocument,inputStyleSheet))) return;
Document *doc = (Document*)(VARGOBJ(CDocument,inputDoc)->node),
*stylesheet = (Document*)(VARGOBJ(CDocument,inputStyleSheet)->node);
if (!doc->childCount)
{
GB.Error("Void document");
return;
}
if (!stylesheet->childCount)
{
GB.Error("Void Style Sheet");
return;
}
char *buffer = 0;
size_t size;
xsltStylesheetPtr sheet = 0;
char *StyleSheetOutput = NULL;
size_t StyleSheetLen = 0;
XML.SerializeXMLNode((Node*)stylesheet, StyleSheetOutput, StyleSheetLen, -1);
StyleSheetOutput =(char*)realloc(StyleSheetOutput, StyleSheetLen + 1);
StyleSheetOutput[StyleSheetLen] = 0;
xmlDoc *xmlStyleSheet = xmlParseDoc((xmlChar*)(StyleSheetOutput));
if(!(sheet=xsltParseStylesheetDoc(xmlStyleSheet)))
{
GB.Error("Invalid style sheet");
return;
}
char *DocumentOutput;
size_t DocumentLen;
XML.SerializeXMLNode((Node*)doc, DocumentOutput, DocumentLen, -1);
DocumentOutput =(char*)realloc(DocumentOutput, DocumentLen + 1);
DocumentOutput[DocumentLen] = 0;
xmlDoc *xmlInputDoc = xmlParseDoc((xmlChar*)(DocumentOutput));
xmlDoc *xmlOutDoc;
xmlChar *buffer = 0;
int size;
xmlOutDoc = xsltApplyStylesheet(sheet, xmlInputDoc, NULL);
if (!xmlOutDoc)
try
{
GB.Error("Unable to apply style sheet");
XSLT_Transform(doc, stylesheet, buffer, size);
}
catch(XSLTException &ex)
{
GB.Error(ex.what());
GB.ReturnNull();
return;
}
xmlDocDumpFormatMemoryEnc(xmlOutDoc ,&buffer, &size, "UTF-8", 1);
Document *outDoc = XML.XMLDocument_New();
/*try
{*/
XML.XMLDocument_SetContent(outDoc, (char*)(buffer),size);
//}
/*catch(XMLParseException &e)
try
{
XML.XMLDocument_SetContent(outDoc, "<?xml version=\"1.0\"?><xml></xml>", 32);
std::cerr << "XSLT Warning : error when parsing output document : " << std::endl << e.what() << std::endl;
}*/
XML.XMLDocument_SetContent(outDoc, (char*)(buffer),size);
}
catch(XMLParseException e)
{
std::cerr << "XSLT Warning : error when parsing output document : " << e.errorWhat << std::endl;
}
free(buffer);
XML.ReturnNode(outDoc);
END_METHOD
BEGIN_METHOD(CXSLT_TransformToString,GB_OBJECT inputDoc;GB_OBJECT inputStyleSheet)
if (GB.CheckObject(VARGOBJ(CDocument,inputDoc))) return;
if (GB.CheckObject(VARGOBJ(CDocument,inputStyleSheet))) return;
Document *doc = (Document*)(VARGOBJ(CDocument,inputDoc)->node),
*stylesheet = (Document*)(VARGOBJ(CDocument,inputStyleSheet)->node);
char *buffer = 0;
size_t size;
try
{
XSLT_Transform(doc, stylesheet, buffer, size);
}
catch(XSLTException &ex)
{
GB.Error(ex.what());
GB.ReturnNull();
return;
}
GB.ReturnNewString(buffer, size);
free(buffer);
END_METHOD
GB_DESC CXsltDesc[] =
@ -120,6 +164,18 @@ GB_DESC CXsltDesc[] =
GB_DECLARE("Xslt", 0), GB_NOT_CREATABLE(),
GB_STATIC_METHOD ("Transform","XmlDocument",CXSLT_Transform,"(Document)XmlDocument;(StyleSheet)XmlDocument;"),
GB_STATIC_METHOD ("TransformToString","s",CXSLT_TransformToString,"(Document)XmlDocument;(StyleSheet)XmlDocument;"),
GB_END_DECLARE
};
XSLTException::XSLTException(const char *error) throw()
{
this->error = error;
}
const char *XSLTException::what()
{
return this->error;
}

View file

@ -31,4 +31,14 @@
extern GB_DESC CXsltDesc[];
#endif
class XSLTException
{
public:
XSLTException(const char *error) throw();
const char* what();
private:
const char *error;
};
#endif