diff options
author | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
---|---|---|
committer | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
commit | b0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch) | |
tree | 22b302342f22843e0815eb5f516c85f1478cbf0b /libtemplate/xmlparser.c | |
download | vdr-plugin-skindesigner-0.0.1.tar.gz vdr-plugin-skindesigner-0.0.1.tar.bz2 |
initial commit version 0.0.10.0.1
Diffstat (limited to 'libtemplate/xmlparser.c')
-rw-r--r-- | libtemplate/xmlparser.c | 728 |
1 files changed, 728 insertions, 0 deletions
diff --git a/libtemplate/xmlparser.c b/libtemplate/xmlparser.c new file mode 100644 index 0000000..f9a723a --- /dev/null +++ b/libtemplate/xmlparser.c @@ -0,0 +1,728 @@ +#include "xmlparser.h" +#include "../config.h" + +using namespace std; + +void SkinDesignerXMLErrorHandler (void * userData, xmlErrorPtr error) { + esyslog("skindesigner: Error in XML: %s", error->message); +} + +cXmlParser::cXmlParser(void) { + doc = NULL; + root = NULL; + ctxt = NULL; + + xmlInitParser(); + initGenericErrorDefaultFunc(NULL); + xmlSetStructuredErrorFunc(NULL, SkinDesignerXMLErrorHandler); + ctxt = xmlNewParserCtxt(); +} + +cXmlParser::~cXmlParser() { + DeleteDocument(); + xmlFreeParserCtxt(ctxt); + xmlCleanupParser(); +} + +/********************************************************************* +* PUBLIC Functions +*********************************************************************/ +bool cXmlParser::ReadView(cTemplateView *view, string xmlFile) { + this->view = view; + + string xmlPath = GetPath(xmlFile); + + if (ctxt == NULL) { + esyslog("skindesigner: Failed to allocate parser context"); + return false; + } + + doc = xmlCtxtReadFile(ctxt, xmlPath.c_str(), NULL, XML_PARSE_NOENT | XML_PARSE_DTDVALID); + + if (doc == NULL) { + esyslog("skindesigner: ERROR: TemplateView %s not parsed successfully.", xmlPath.c_str()); + return false; + } + if (ctxt->valid == 0) { + esyslog("skindesigner: Failed to validate %s", xmlPath.c_str()); + return false; + } + + root = xmlDocGetRootElement(doc); + + if (root == NULL) { + esyslog("skindesigner: ERROR: TemplateView %s is empty", xmlPath.c_str()); + return false; + } + + if (xmlStrcmp(root->name, (const xmlChar *) view->GetViewName())) { + return false; + } + return true; +} + +bool cXmlParser::ReadGlobals(cGlobals *globals, string xmlFile) { + this->globals = globals; + + string xmlPath = GetPath(xmlFile); + + if (ctxt == NULL) { + esyslog("skindesigner: Failed to allocate parser context"); + return false; + } + + doc = xmlCtxtReadFile(ctxt, xmlPath.c_str(), NULL, XML_PARSE_NOENT | XML_PARSE_DTDVALID); + + if (doc == NULL ) { + esyslog("skindesigner: ERROR: Globals %s not parsed successfully.", xmlPath.c_str()); + return false; + } + + root = xmlDocGetRootElement(doc); + + if (ctxt->valid == 0) { + esyslog("skindesigner: Failed to validate %s", xmlPath.c_str()); + return false; + } + + if (root == NULL) { + esyslog("skindesigner: ERROR: Globals %s is empty", xmlPath.c_str()); + return false; + } + + if (xmlStrcmp(root->name, (const xmlChar *) "globals")) { + return false; + } + return true; +} + +bool cXmlParser::ParseView(void) { + vector<pair<string, string> > rootAttribs; + ParseAttributes(root->properties, root, rootAttribs); + + if (!view) + return false; + + view->SetParameters(rootAttribs); + + xmlNodePtr node = root->xmlChildrenNode; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (view->ValidSubView((const char*)node->name)) { + ParseSubView(node); + } else if (view->ValidViewElement((const char*)node->name)) { + bool debugViewElement = DebugViewElement(node); + ParseViewElement(node->name, node->xmlChildrenNode, debugViewElement); + } else if (view->ValidViewList((const char*)node->name)) { + ParseViewList(node); + } else { + return false; + } + + node = node->next; + } + + return true; + +} + +bool cXmlParser::ParseGlobals(void) { + xmlNodePtr node = root->xmlChildrenNode; + + while (node != NULL) { + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (!xmlStrcmp(node->name, (const xmlChar *) "colors")) { + ParseGlobalColors(node->xmlChildrenNode); + node = node->next; + continue; + } else if (!xmlStrcmp(node->name, (const xmlChar *) "variables")) { + ParseGlobalVariables(node->xmlChildrenNode); + node = node->next; + continue; + } else if (!xmlStrcmp(node->name, (const xmlChar *) "fonts")) { + ParseGlobalFonts(node->xmlChildrenNode); + node = node->next; + continue; + } else if (!xmlStrcmp(node->name, (const xmlChar *) "translations")) { + ParseTranslations(node->xmlChildrenNode); + node = node->next; + continue; + } + node = node->next; + } + + return true; + +} + +void cXmlParser::DeleteDocument(void) { + if (doc) { + xmlFreeDoc(doc); + doc = NULL; + } +} + +/********************************************************************* +* PRIVATE Functions +*********************************************************************/ + +string cXmlParser::GetPath(string xmlFile) { + return *cString::sprintf("%s%s/xmlfiles/%s", *config.skinPath, Setup.OSDTheme, xmlFile.c_str()); +} + +void cXmlParser::ParseGlobalColors(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "color")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *colName = NULL; + xmlChar *colValue = NULL; + bool ok = false; + while (NULL != attr) { + if (xmlStrcmp(attr->name, (const xmlChar *) "name")) { + attr = attr->next; + continue; + } + ok = true; + colName = xmlGetProp(node, attr->name); + attr = attr->next; + } + if (ok) { + colValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (colName && colValue) + InsertColor((const char*)colName, (const char*)colValue); + } + if (colName) + xmlFree(colName); + if (colValue) + xmlFree(colValue); + node = node->next; + } +} + +void cXmlParser::InsertColor(string name, string value) { + if (value.size() != 8) + return; + std::stringstream str; + str << value; + tColor colVal; + str >> std::hex >> colVal; + globals->colors.insert(pair<string, tColor>(name, colVal)); +} + +void cXmlParser::ParseGlobalVariables(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "var")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *varName = NULL; + xmlChar *varType = NULL; + xmlChar *varValue = NULL; + while (NULL != attr) { + if (!xmlStrcmp(attr->name, (const xmlChar *) "name")) { + varName = xmlGetProp(node, attr->name); + } else if (!xmlStrcmp(attr->name, (const xmlChar *) "type")) { + varType = xmlGetProp(node, attr->name); + } else { + attr = attr->next; + continue; + } + attr = attr->next; + } + varValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (varName && varType && varValue) + InsertVariable((const char*)varName, (const char*)varType, (const char*)varValue); + if (varName) + xmlFree(varName); + if (varType) + xmlFree(varType); + if (varValue) + xmlFree(varValue); + node = node->next; + } +} + +void cXmlParser::InsertVariable(string name, string type, string value) { + if (!type.compare("int")) { + int val = atoi(value.c_str()); + globals->intVars.insert(pair<string, int>(name, val)); + } else if (!type.compare("string")) { + globals->stringVars.insert(pair<string, string>(name, value)); + } +} + +void cXmlParser::ParseGlobalFonts(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "font")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *fontName = NULL; + xmlChar *fontValue = NULL; + bool ok = false; + while (NULL != attr) { + if (xmlStrcmp(attr->name, (const xmlChar *) "name")) { + attr = attr->next; + continue; + } + ok = true; + fontName = xmlGetProp(node, attr->name); + attr = attr->next; + } + if (ok) { + fontValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (fontName && fontValue) + globals->fonts.insert(pair<string, string>((const char*)fontName, (const char*)fontValue)); + } + if (fontName) + xmlFree(fontName); + if (fontValue) + xmlFree(fontValue); + node = node->next; + } +} + +void cXmlParser::ParseTranslations(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "token")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *tokenName; + bool ok = false; + while (NULL != attr) { + if (xmlStrcmp(attr->name, (const xmlChar *) "name")) { + attr = attr->next; + continue; + } + ok = true; + tokenName = xmlGetProp(node, attr->name); + attr = attr->next; + } + if (!ok) + continue; + map < string, string > tokenTranslations; + xmlNodePtr nodeTrans = node->xmlChildrenNode; + while (nodeTrans != NULL) { + if (nodeTrans->type != XML_ELEMENT_NODE) { + nodeTrans = nodeTrans->next; + continue; + } + xmlChar *language = NULL; + if (xmlStrcmp(nodeTrans->name, (const xmlChar *) "trans")) { + nodeTrans = nodeTrans->next; + continue; + } + xmlAttrPtr attrTrans = nodeTrans->properties; + if (attrTrans == NULL) { + nodeTrans = nodeTrans->next; + continue; + } + ok = false; + + while (NULL != attrTrans) { + if (!ok && xmlStrcmp(attrTrans->name, (const xmlChar *) "lang")) { + attrTrans = attrTrans->next; + continue; + } + ok = true; + language = xmlGetProp(nodeTrans, attrTrans->name); + attrTrans = attrTrans->next; + } + if (!ok) + continue; + xmlChar *value = NULL; + value = xmlNodeListGetString(doc, nodeTrans->xmlChildrenNode, 1); + if (language && value) + tokenTranslations.insert(pair<string, string>((const char*)language, (const char*)value)); + if (language) + xmlFree(language); + if (value) + xmlFree(value); + nodeTrans = nodeTrans->next; + } + globals->translations.insert(pair<string, map < string, string > >((const char*)tokenName, tokenTranslations)); + xmlFree(tokenName); + node = node->next; + } +} + +bool cXmlParser::ParseSubView(xmlNodePtr node) { + if (!node) + return false; + + if (!view) + return false; + + cTemplateView *subView = new cTemplateViewMenu(); + view->AddSubView((const char*)node->name, subView); + + vector<pair<string, string> > subViewAttribs; + ParseAttributes(node->properties, node, subViewAttribs); + + subView->SetParameters(subViewAttribs); + + xmlNodePtr childNode = node->xmlChildrenNode; + + while (childNode != NULL) { + + if (childNode->type != XML_ELEMENT_NODE) { + childNode = childNode->next; + continue; + } + + if (subView->ValidViewElement((const char*)childNode->name)) { + bool debugViewElement = DebugViewElement(childNode); + ParseViewElement(childNode->name, childNode->xmlChildrenNode, debugViewElement, subView); + } else if (subView->ValidViewList((const char*)childNode->name)) { + ParseViewList(childNode, subView); + } else if (!xmlStrcmp(childNode->name, (const xmlChar *) "tab")) { + ParseViewTab(childNode, subView); + } else { + return false; + } + + childNode = childNode->next; + } + + + + return true; + +} + +void cXmlParser::ParseViewElement(const xmlChar * viewElement, xmlNodePtr node, bool debugVE, cTemplateView *subView) { + if (!node) + return; + + if (!view) + return; + + if (debugVE) { + dsyslog("skindesigner: activating debugging of viewElement %s", (const char*)viewElement); + } + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (xmlStrcmp(node->name, (const xmlChar *) "area") && xmlStrcmp(node->name, (const xmlChar *) "areascroll")) { + esyslog("skindesigner: invalid tag \"%s\"", node->name); + node = node->next; + continue; + } + + xmlAttrPtr attr = node->properties; + vector<pair<string, string> > attribs; + ParseAttributes(attr, node, attribs); + + cTemplatePixmap *pix = new cTemplatePixmap(); + if (!xmlStrcmp(node->name, (const xmlChar *) "areascroll")) { + pix->SetScrolling(); + } + pix->SetParameters(attribs); + ParseFunctionCalls(node->xmlChildrenNode, pix); + if (subView) + subView->AddPixmap((const char*)viewElement, pix, debugVE); + else + view->AddPixmap((const char*)viewElement, pix, debugVE); + + node = node->next; + } +} + +void cXmlParser::ParseViewList(xmlNodePtr parentNode, cTemplateView *subView) { + if (!parentNode || !view) + return; + + xmlAttrPtr attr = parentNode->properties; + vector<pair<string, string> > attribs; + ParseAttributes(attr, parentNode, attribs); + + cTemplateViewList *viewList = new cTemplateViewList(); + viewList->SetGlobals(globals); + viewList->SetParameters(attribs); + + xmlNodePtr node = parentNode->xmlChildrenNode; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (!xmlStrcmp(node->name, (const xmlChar *) "currentelement")) { + xmlNodePtr childNode = node->xmlChildrenNode; + if (!childNode) + continue; + cTemplateViewElement *currentElement = new cTemplateViewElement(); + xmlAttrPtr attrCur = node->properties; + vector<pair<string, string> > attribsCur; + ParseAttributes(attrCur, node, attribsCur); + currentElement->SetGlobals(globals); + currentElement->SetParameters(attribsCur); + bool debugCurrent = false; + for (vector<pair<string, string> >::iterator it = attribsCur.begin(); it != attribsCur.end(); it++) { + if (!(it->first).compare("debug")) { + debugCurrent = true; + break; + } + } + if (debugCurrent) + currentElement->ActivateDebugTokens(); + while (childNode != NULL) { + if (childNode->type != XML_ELEMENT_NODE) { + childNode = childNode->next; + continue; + } + if ((!xmlStrcmp(childNode->name, (const xmlChar *) "area")) || (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll"))) { + xmlAttrPtr attrPix = childNode->properties; + vector<pair<string, string> > attribsPix; + ParseAttributes(attrPix, childNode, attribsPix); + cTemplatePixmap *pix = new cTemplatePixmap(); + pix->SetParameters(attribsPix); + ParseFunctionCalls(childNode->xmlChildrenNode, pix); + if (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll")) { + pix->SetScrolling(); + } + currentElement->AddPixmap(pix); + } + childNode = childNode->next; + } + viewList->AddCurrentElement(currentElement); + } else if (!xmlStrcmp(node->name, (const xmlChar *) "listelement")) { + bool debugViewList = DebugViewElement(node); + xmlNodePtr childNode = node->xmlChildrenNode; + if (!childNode) + continue; + cTemplateViewElement *listElement = new cTemplateViewElement(); + if (debugViewList) + listElement->ActivateDebugTokens(); + while (childNode != NULL) { + if (childNode->type != XML_ELEMENT_NODE) { + childNode = childNode->next; + continue; + } + if ((!xmlStrcmp(childNode->name, (const xmlChar *) "area")) || (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll"))) { + xmlAttrPtr attrPix = childNode->properties; + vector<pair<string, string> > attribsPix; + ParseAttributes(attrPix, childNode, attribsPix); + cTemplatePixmap *pix = new cTemplatePixmap(); + pix->SetParameters(attribsPix); + ParseFunctionCalls(childNode->xmlChildrenNode, pix); + if (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll")) { + pix->SetScrolling(); + } + listElement->AddPixmap(pix); + } + childNode = childNode->next; + } + viewList->AddListElement(listElement); + } else { + node = node->next; + continue; + } + node = node->next; + } + if (subView) + subView->AddViewList((const char*)parentNode->name, viewList); + else + view->AddViewList((const char*)parentNode->name, viewList); +} + +void cXmlParser::ParseViewTab(xmlNodePtr parentNode, cTemplateView *subView) { + if (!parentNode || !view || !subView) + return; + + xmlAttrPtr attr = parentNode->properties; + vector<pair<string, string> > attribs; + ParseAttributes(attr, parentNode, attribs); + + cTemplateViewTab *viewTab = new cTemplateViewTab(); + viewTab->SetGlobals(globals); + viewTab->SetParameters(attribs); + viewTab->SetScrolling(); + xmlNodePtr node = parentNode->xmlChildrenNode; + ParseFunctionCalls(node, viewTab); + + subView->AddViewTab(viewTab); +} + +void cXmlParser::ParseFunctionCalls(xmlNodePtr node, cTemplatePixmap *pix) { + if (!node) + return; + + if (!view) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (!xmlStrcmp(node->name, (const xmlChar *) "loop")) { + xmlNodePtr childNode = node->xmlChildrenNode; + if (!childNode) + continue; + xmlAttrPtr attr = node->properties; + vector<pair<string, string> > attribs; + ParseAttributes(attr, node, attribs); + cTemplateLoopFunction *loopFunc = new cTemplateLoopFunction(); + loopFunc->SetParameters(attribs); + ParseLoopFunctionCalls(childNode, loopFunc); + pix->AddLoopFunction(loopFunc); + node = node->next; + } else if (view->ValidFunction((const char*)node->name)) { + xmlAttrPtr attr = node->properties; + vector<pair<string, string> > attribs; + ParseAttributes(attr, node, attribs); + pix->AddFunction((const char*)node->name, attribs); + node = node->next; + } else { + node = node->next; + continue; + } + + } +} + +void cXmlParser::ParseLoopFunctionCalls(xmlNodePtr node, cTemplateLoopFunction *loopFunc) { + if (!node) + return; + + if (!view) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (view->ValidFunction((const char*)node->name)) { + xmlAttrPtr attr = node->properties; + vector<pair<string, string> > attribs; + ParseAttributes(attr, node, attribs); + loopFunc->AddFunction((const char*)node->name, attribs); + node = node->next; + } else { + node = node->next; + continue; + } + + } +} + +bool cXmlParser::ParseAttributes(xmlAttrPtr attr, xmlNodePtr node, vector<pair<string, string> > &attribs) { + if (attr == NULL) { + return false; + } + + if (!view) + return false; + + while (NULL != attr) { + + string name = (const char*)attr->name; + if (!name.compare("debug")) { + attribs.push_back(pair<string, string>((const char*)attr->name, "true")); + attr = attr->next; + continue; + } + + xmlChar *value = NULL; + value = xmlGetProp(node, attr->name); + if (!view->ValidAttribute((const char*)node->name, (const char*)attr->name)) { + attr = attr->next; + if (value) + xmlFree(value); + continue; + } + if (value) + attribs.push_back(pair<string, string>((const char*)attr->name, (const char*)value)); + attr = attr->next; + if (value) + xmlFree(value); + } + return true; +} + +bool cXmlParser::DebugViewElement(xmlNodePtr node) { + xmlAttrPtr attr = node->properties; + vector<pair<string, string> > attribs; + ParseAttributes(attr, node, attribs); + for (vector<pair<string, string> >::iterator it = attribs.begin(); it != attribs.end(); it++) { + if (!(it->first).compare("debug")) + return true; + } + return false; +} |