vdr-plugin-skindesigner/extensions/libxmlwrapper.c

190 lines
4.8 KiB
C

#include "helpers.h"
#include "libxmlwrapper.h"
void SkinDesignerXMLErrorHandler (void * userData, xmlErrorPtr error) {
esyslog("skindesigner: Error in XML: %s", error->message);
}
cLibXMLWrapper::cLibXMLWrapper(void) {
ctxt = NULL;
doc = NULL;
root = NULL;
initGenericErrorDefaultFunc(NULL);
xmlSetStructuredErrorFunc(NULL, SkinDesignerXMLErrorHandler);
ctxt = xmlNewParserCtxt();
}
cLibXMLWrapper::~cLibXMLWrapper() {
DeleteDocument();
xmlFreeParserCtxt(ctxt);
}
void cLibXMLWrapper::InitLibXML() {
xmlInitParser();
}
void cLibXMLWrapper::CleanupLibXML() {
xmlCleanupParser();
}
void cLibXMLWrapper::DeleteDocument(void) {
if (doc) {
xmlFreeDoc(doc);
doc = NULL;
}
while (!nodeStack.empty())
nodeStack.pop();
}
bool cLibXMLWrapper::ReadXMLFile(const char *path, bool validate) {
if (!ctxt) {
esyslog("skindesigner: Failed to allocate parser context");
return false;
}
if (!FileExists(path)) {
dsyslog("skindesigner: reading XML Template %s failed", path);
return false;
}
if (validate)
doc = xmlCtxtReadFile(ctxt, path, NULL, XML_PARSE_NOENT | XML_PARSE_DTDVALID);
else
doc = xmlCtxtReadFile(ctxt, path, NULL, XML_PARSE_NOENT);
if (!doc) {
dsyslog("skindesigner: reading XML Template %s failed", path);
return false;
}
return true;
}
bool cLibXMLWrapper::SetDocument(void) {
if (!doc)
return false;
root = xmlDocGetRootElement(doc);
nodeStack.push(root);
if (root == NULL) {
esyslog("skindesigner: ERROR: XML File is empty");
return false;
}
return true;
}
bool cLibXMLWrapper::Validate(void) {
if (!ctxt)
return false;
if (ctxt->valid == 0) {
esyslog("skindesigner: Failed to validate XML File");
return false;
}
return true;
}
bool cLibXMLWrapper::CheckNodeName(const char *name) {
if (nodeStack.empty())
return false;
xmlNodePtr current = nodeStack.top();
if (xmlStrcmp(current->name, (const xmlChar *) name)) {
return false;
}
return true;
}
const char *cLibXMLWrapper::NodeName(void) {
xmlNodePtr current = nodeStack.top();
return (const char*)current->name;
}
vector<stringpair> cLibXMLWrapper::ParseAttributes(void) {
vector<stringpair> attributes;
if (nodeStack.empty())
return attributes;
xmlNodePtr current = nodeStack.top();
xmlAttrPtr attrPtr = current->properties;
if (attrPtr == NULL) {
return attributes;
}
while (NULL != attrPtr) {
string name = (const char*)attrPtr->name;
xmlChar *value = NULL;
value = xmlGetProp(current, attrPtr->name);
if (value)
attributes.push_back(stringpair((const char*)attrPtr->name, (const char*)value));
attrPtr = attrPtr->next;
if (value)
xmlFree(value);
}
return attributes;
}
bool cLibXMLWrapper::LevelDown(void) {
if (nodeStack.empty())
return false;
xmlNodePtr current = nodeStack.top();
xmlNodePtr child = current->xmlChildrenNode;
while (child && child->type != XML_ELEMENT_NODE) {
child = child->next;
}
if (!child)
return false;
nodeStack.push(child);
return true;
}
bool cLibXMLWrapper::LevelUp(void) {
if (nodeStack.size() == 1)
return false;
nodeStack.pop();
return true;
}
bool cLibXMLWrapper::NextNode(void) {
xmlNodePtr current = nodeStack.top();
current = current->next;
while (current && current->type != XML_ELEMENT_NODE) {
current = current->next;
}
if (!current)
return false;
nodeStack.pop();
nodeStack.push(current);
return true;
}
bool cLibXMLWrapper::GetAttribute(string &name, string &value) {
bool ok = false;
xmlNodePtr current = nodeStack.top();
xmlAttrPtr attr = current->properties;
if (attr == NULL) {
return ok;
}
xmlChar *xmlValue = NULL;
while (NULL != attr) {
if (xmlStrcmp(attr->name, (const xmlChar *) name.c_str())) {
attr = attr->next;
continue;
}
ok = true;
xmlValue = xmlGetProp(current, attr->name);
if (xmlValue) {
value = (const char*)xmlValue;
xmlFree(xmlValue);
}
break;
}
return ok;
}
bool cLibXMLWrapper::GetNodeValue(string &value) {
xmlChar *val = NULL;
xmlNodePtr current = nodeStack.top();
val = xmlNodeListGetString(doc, current->xmlChildrenNode, 1);
if (val) {
value = (const char*)val;
xmlFree(val);
return true;
}
value = "";
return false;
}