1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
43 #include <libxml/parser.h>
45 #include <anna/core/functions.hpp>
46 #include <anna/core/tracing/Logger.hpp>
47 #include <anna/core/tracing/TraceMethod.hpp>
48 #include <anna/core/tracing/TraceFunction.hpp>
49 #include <anna/core/mt/Guard.hpp>
51 #include <anna/xml/xml.hpp>
52 #include <anna/xml/internal/sccs.hpp>
57 char Parser::st_text [1024] = "";
58 RuntimeException* Parser::st_exception = NULL;
65 a_context = (xmlValidCtxtPtr) xmlMalloc(sizeof(xmlValidCtxt));
66 a_context->error = errorHandler;
67 a_context->warning = warningHandler;
77 const Node* Parser::apply(const Document& document)
78 throw(RuntimeException) {
79 LOGMETHOD(TraceMethod tf("anna::xml::Parser", "apply(Document)", ANNA_FILE_LOCATION));
82 apply(const_cast <_xmlDoc*>(document.a_handle));
86 const Node* Parser::apply(const Document& document, const DTD& dtd)
87 throw(RuntimeException) {
88 LOGMETHOD(TraceMethod tf("anna::xml::Parser", "apply(Document,DTD)", ANNA_FILE_LOCATION));
91 dtd.validate(a_context, const_cast <_xmlDoc*>(document.a_handle));
92 apply(const_cast <_xmlDoc*>(document.a_handle));
96 void Parser::apply(_xmlDoc* document)
97 throw(RuntimeException) {
98 LOGMETHOD(TraceMethod tf("anna::xml::Parser", "apply (_xmlDoc)", ANNA_FILE_LOCATION));
101 if((root = xmlDocGetRootElement(document)) == NULL)
102 throw RuntimeException("Error interpreting XML document", ANNA_FILE_LOCATION);
104 setupEncoding(document);
107 a_root = new Node((const char*) root->name);
109 a_root->setName((const char*) root->name);
111 for(xmlNs* ns = root->nsDef; ns != NULL; ns = ns->next)
112 a_root->createNamespace((const char*) ns->prefix, (const char*) ns->href);
115 a_root->setNamespace(a_root->namespace_find((const char*) root->ns->prefix));
117 attributes(a_root, root->properties);
118 children(a_root, root->children);
121 void Parser::children(Node* node, xmlNode* xmlNode)
122 throw(RuntimeException) {
127 while(xmlNode != NULL) {
128 switch(xmlNode->type) {
129 case XML_ELEMENT_NODE:
130 child = node->createChild((const char*) xmlNode->name);
132 for(xmlNs* ns = xmlNode->nsDef; ns != NULL; ns = ns->next)
133 if(ns->prefix != NULL)
134 a_root->createNamespace((const char*) ns->prefix, (const char*) ns->href);
136 if(xmlNode->ns != NULL && xmlNode->ns->prefix != NULL)
137 child->setNamespace(node->namespace_find((const char*) xmlNode->ns->prefix));
139 attributes(child, xmlNode->properties);
140 children(child, xmlNode->children);
143 w = (const char*) xmlNode->content;
147 if(isspace(*w) == false) {
155 if(isSeparator == false)
156 node->createText(decode(xmlNode->content));
161 xmlNode = xmlNode->next;
165 void Parser::attributes(Node* node, xmlAttr* attribute)
166 throw(RuntimeException) {
168 const Namespace* ns = NULL;
170 while(attribute != NULL) {
171 ns = (attribute->ns == NULL) ? NULL : node->namespace_find((const char*) attribute->ns->prefix);
172 value = (attribute->children != NULL) ? decode(attribute->children->content) : "";
173 node->createAttribute((const char*) attribute->name, value, ns);
174 attribute = attribute->next;
179 void Parser::errorHandler(void *ctx, const char *msg, ...)
183 vsprintf(st_text, msg, ap);
185 for(char* aux = st_text; *aux; aux ++)
190 Logger::write(Logger::Error, st_text, ANNA_FILE_LOCATION);
194 void Parser::warningHandler(void *ctx, const char *msg, ...)
198 if(Logger::isActive(Logger::Warning)) {
200 vsprintf(st_text, msg, ap);
202 for(char* aux = st_text; *aux; aux ++)
207 Logger::write(Logger::Warning, st_text, ANNA_FILE_LOCATION);
211 // La metodo que invoque a este debe hacerlo con una secci�n cr�tica activa.
218 void Parser::setupEncoding(_xmlDoc* document)
220 if(document->encoding != NULL) {
223 if(a_buffEncode == NULL)
224 a_buffEncode = new DataBlock(true);
226 a_buffEncode->clear();
231 string msg("anna::xml::Parser::setupEncoding | Encoding: ");
232 msg += (document->encoding == NULL) ? "none" : (const char*) document->encoding;
233 Logger::debug(msg, ANNA_FILE_LOCATION);
237 const char* Parser::decode(const unsigned char* source)
239 if(a_encoding == false)
240 return (const char*) source;
242 if(xmlCheckUTF8(source) == 0)
243 return (const char*) source;
245 int srcLen = xmlStrlen(source);
246 a_buffEncode->clear();
247 a_buffEncode->allocate(srcLen + 1);
248 unsigned char* target = (unsigned char*) a_buffEncode->getData();
250 UTF8Toisolat1(target, &trgLen, source, &srcLen);
252 return (const char*) target;