1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
15 #include <libxml/parser.h>
17 #include <anna/core/functions.hpp>
18 #include <anna/core/tracing/Logger.hpp>
19 #include <anna/core/tracing/TraceMethod.hpp>
20 #include <anna/core/tracing/TraceFunction.hpp>
21 #include <anna/core/mt/Guard.hpp>
23 #include <anna/xml/xml.hpp>
24 #include <anna/xml/internal/sccs.hpp>
29 char Parser::st_text [1024] = "";
30 RuntimeException* Parser::st_exception = NULL;
37 a_context = (xmlValidCtxtPtr) xmlMalloc(sizeof(xmlValidCtxt));
38 a_context->error = errorHandler;
39 a_context->warning = warningHandler;
49 const Node* Parser::apply(const Document& document)
50 throw(RuntimeException) {
51 LOGMETHOD(TraceMethod tf("anna::xml::Parser", "apply(Document)", ANNA_FILE_LOCATION));
54 apply(const_cast <_xmlDoc*>(document.a_handle));
58 const Node* Parser::apply(const Document& document, const DTD& dtd)
59 throw(RuntimeException) {
60 LOGMETHOD(TraceMethod tf("anna::xml::Parser", "apply(Document,DTD)", ANNA_FILE_LOCATION));
63 dtd.validate(a_context, const_cast <_xmlDoc*>(document.a_handle));
64 apply(const_cast <_xmlDoc*>(document.a_handle));
68 void Parser::apply(_xmlDoc* document)
69 throw(RuntimeException) {
70 LOGMETHOD(TraceMethod tf("anna::xml::Parser", "apply (_xmlDoc)", ANNA_FILE_LOCATION));
73 if((root = xmlDocGetRootElement(document)) == NULL)
74 throw RuntimeException("Error interpreting XML document", ANNA_FILE_LOCATION);
76 setupEncoding(document);
79 a_root = new Node((const char*) root->name);
81 a_root->setName((const char*) root->name);
83 for(xmlNs* ns = root->nsDef; ns != NULL; ns = ns->next)
84 a_root->createNamespace((const char*) ns->prefix, (const char*) ns->href);
87 a_root->setNamespace(a_root->namespace_find((const char*) root->ns->prefix));
89 attributes(a_root, root->properties);
90 children(a_root, root->children);
93 void Parser::children(Node* node, xmlNode* xmlNode)
94 throw(RuntimeException) {
99 while(xmlNode != NULL) {
101 if((xmlNode->type) == XML_ELEMENT_NODE) {
102 child = node->createChild((const char*) xmlNode->name);
104 for(xmlNs* ns = xmlNode->nsDef; ns != NULL; ns = ns->next)
105 if(ns->prefix != NULL)
106 a_root->createNamespace((const char*) ns->prefix, (const char*) ns->href);
108 if(xmlNode->ns != NULL && xmlNode->ns->prefix != NULL)
109 child->setNamespace(node->namespace_find((const char*) xmlNode->ns->prefix));
111 attributes(child, xmlNode->properties);
112 children(child, xmlNode->children);
114 else if((xmlNode->type) == XML_TEXT_NODE) {
115 w = (const char*) xmlNode->content;
119 if(isspace(*w) == false) {
126 if(isSeparator == false)
127 node->createText(decode(xmlNode->content));
131 xmlNode = xmlNode->next;
135 void Parser::attributes(Node* node, xmlAttr* attribute)
136 throw(RuntimeException) {
138 const Namespace* ns = NULL;
140 while(attribute != NULL) {
141 ns = (attribute->ns == NULL) ? NULL : node->namespace_find((const char*) attribute->ns->prefix);
142 value = (attribute->children != NULL) ? decode(attribute->children->content) : "";
143 node->createAttribute((const char*) attribute->name, value, ns);
144 attribute = attribute->next;
149 void Parser::errorHandler(void *ctx, const char *msg, ...)
153 vsprintf(st_text, msg, ap);
155 for(char* aux = st_text; *aux; aux ++)
160 Logger::write(Logger::Error, st_text, ANNA_FILE_LOCATION);
164 void Parser::warningHandler(void *ctx, const char *msg, ...)
168 if(Logger::isActive(Logger::Warning)) {
170 vsprintf(st_text, msg, ap);
172 for(char* aux = st_text; *aux; aux ++)
177 Logger::write(Logger::Warning, st_text, ANNA_FILE_LOCATION);
181 // La metodo que invoque a este debe hacerlo con una secci�n cr�tica activa.
188 void Parser::setupEncoding(_xmlDoc* document)
190 if(document->encoding != NULL) {
193 if(a_buffEncode == NULL)
194 a_buffEncode = new DataBlock(true);
196 a_buffEncode->clear();
201 string msg("anna::xml::Parser::setupEncoding | Encoding: ");
202 msg += (document->encoding == NULL) ? "none" : (const char*) document->encoding;
203 Logger::debug(msg, ANNA_FILE_LOCATION);
207 const char* Parser::decode(const unsigned char* source)
209 if(a_encoding == false)
210 return (const char*) source;
212 if(xmlCheckUTF8(source) == 0)
213 return (const char*) source;
215 int srcLen = xmlStrlen(source);
216 a_buffEncode->clear();
217 a_buffEncode->allocate(srcLen + 1);
218 unsigned char* target = (unsigned char*) a_buffEncode->getData();
220 UTF8Toisolat1(target, &trgLen, source, &srcLen);
222 return (const char*) target;