/** * Given an XML @p filename, open it, validate schema, process nodes, * convert and save it in the @p ks KeySet. * * Currently, the XML file can have many root @c @<keyset@> and @c @<key@> nodes. * They will all be reduced to simple keys returned in @p ks. * * To check if the xml file is valid (best before you read from it): * @code #include char schemaPath[513]; schemaPath[0]=0; ret=kdbGetString(handle, KDB_SCHEMA_PATH_KEY,schemaPath,sizeof(schemaPath)); if (ret==0) ret = isValidXML(filename,schemaPath); else ret = isValidXML(filename,KDB_SCHEMA_PATH); * @endcode * * @retval -1 on error * @retval 0 if file could not be opened * @param ks the keyset * @param filename the file to parse * @ingroup stream */ int ksFromXMLfile(KeySet *ks, const char *filename) { xmlTextReaderPtr reader = 0; xmlDocPtr doc = 0; int ret=0; doc = xmlParseFile(filename); if (doc==0) { // TODO: distinguish between parser errors and // permission errors? xmlCleanupParser(); return -1; } reader=xmlReaderWalker(doc); if (reader) { ret=ksFromXMLReader(ks,reader); xmlFreeTextReader (reader); } else { ret = -1; } xmlFreeDoc(doc); xmlCleanupParser(); return ret; }
vector<string> XMLReader::parseDocument(const xmlDocPtr doc, ElementHandler &elementHandler) { vector<string> updatedKeys; xmlTextReaderPtr reader = xmlReaderWalker(doc); if (reader==NULL) throw std::runtime_error("Could not create xml-reader."); int top_level_depth = gobbleUntilStartElement(reader, "State"); if ( top_level_depth>=0 ) { // Ok, "State" was found, continue scanning for named elements... bool state_end_found=false, processing_complex_type=false; string complex_type_name; model::StringStringPTree ptree; ptree.add("root", 0); vector<model::StringStringPTree::iterator> prev_pos; // Recursion through stack-usage model::StringStringPTree::iterator current_pos = ptree.begin(); int prev_depth = top_level_depth; while ( !state_end_found ) { string name, value; int depth; if ( nextTypeContainsChildren(reader, "State", name, value, state_end_found, depth) ) { if (depth==top_level_depth+1) { processing_complex_type = true; // We are at the root of a complex type. complex_type_name = name; } current_pos->second.add(name, "contains fields on the level below, no value here"); prev_pos.push_back(current_pos); current_pos = (--current_pos->second.end()); // "Recursive call" } else { if ( ( (depth==top_level_depth+1) && (processing_complex_type) ) || ( state_end_found && (processing_complex_type) ) ) { // End of tree for complex type has been reached processing_complex_type = false; elementHandler.updateElementFromPTree(complex_type_name, ptree.begin()->second); updatedKeys.push_back(complex_type_name); } if (!state_end_found) { if (depth<prev_depth) { // We leave the level and ascend. Must pop back to a previous position in the tree. ("Recursive return.") for (int i=0; i<prev_depth-depth-1; i++) prev_pos.pop_back(); current_pos = prev_pos.back(); prev_pos.pop_back(); } if (processing_complex_type) { // We are building the tree for a complex type update, so add (name, val) to ptree. current_pos->second.add(name, value); } else { // A simple type, call the appropriate method to update the state right away. elementHandler.updateElementFromString(name, value); updatedKeys.push_back(name); } } } prev_depth = depth; } } xmlFreeTextReader( reader ); return updatedKeys; }
static Buffer *extractText(htmlDocPtr doc) { char * term = "\0"; Buffer *buf = new_buffer(256); xmlTextReaderPtr reader = xmlReaderWalker(doc); while(xmlTextReaderRead(reader)){ processNode(reader, buf); } xmlFreeTextReader(reader); buffer_in(buf, term, 1); return buf; }
/* * call-seq: * XML::Reader.document(doc) -> XML::Reader * * Create an new reader for the specified document. */ VALUE rxml_reader_document(VALUE klass, VALUE doc) { xmlDocPtr xdoc; xmlTextReaderPtr xreader; Data_Get_Struct(doc, xmlDoc, xdoc); xreader = xmlReaderWalker(xdoc); if (xreader == NULL) rxml_raise(&xmlLastError); return rxml_reader_wrap(xreader); }
bool MMSXMLServerInterface::funcSendEvent(xmlNodePtr node, string *answer) { xmlChar *heading, *name, *value;/**pluginid*/ xmlTextReader *reader; MMSEvent *event; if(!node || !answer) return false; /* get attributes */ heading = xmlGetProp(node, (const xmlChar*)"heading"); reader = xmlReaderWalker(node->doc); //pluginid = xmlTextReaderGetAttribute(reader, (const xmlChar*)"pluginid"); if(!heading /*|| !pluginid*/) return false; event = new MMSEvent((const char*)heading); /* through <func/> childs */ while(xmlTextReaderRead(reader)) { name = (xmlChar*)xmlTextReaderConstName(reader); if(name && xmlStrEqual(name, (const xmlChar*)"param")) { while(xmlTextReaderMoveToNextAttribute(reader)) { name = xmlTextReaderName(reader); value = xmlTextReaderValue(reader); event->setData((const char*)name, (const char*)value); xmlFree(name); xmlFree(value); } } } /* build answer */ *answer = "<ret/>"; event->send(); return true; }
static Pvoid_t tokenize_uris(htmlDocPtr doc, Pvoid_t features) { xmlTextReaderPtr reader = xmlReaderWalker(doc); while (xmlTextReaderRead(reader)) { int type = xmlTextReaderNodeType(reader); if (type == XML_ELEMENT_NODE) { char *uri = (char *) xmlTextReaderGetAttribute(reader, BAD_CAST "href"); if (uri) { features = tokenize_uri(uri, features); free(uri); } uri = (char*) xmlTextReaderGetAttribute(reader, BAD_CAST "src"); if (uri) { features = tokenize_uri(uri, features); free(uri); } } } xmlFreeTextReader(reader); return features; }
/** Parse the 'detailed' Anime fields from HTML * * */ std::shared_ptr<Anime> AnimeSerializer::deserialize_details(const std::string& xml) const { typedef std::unique_ptr<xmlChar, XmlCharDeleter> xmlStringUPtr; auto res = std::make_shared<Anime>(); std::unique_ptr<char[]> cstr(new char[xml.size()]); std::memcpy(cstr.get(), xml.c_str(), xml.size()); std::unique_ptr<xmlDoc, XmlDocDeleter> doc(htmlReadMemory(cstr.get(), xml.size(), "http://myanimelist.net/", nullptr, HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_NONET)); std::unique_ptr<xmlTextReader, xmlTextReaderDeleter> reader(xmlReaderWalker(doc.get())); if (!reader) { std::cerr << "Error: Couldn't create XML reader" << std::endl; std::cerr << "XML follows: " << xml << std::endl; return nullptr; } enum { PRIORITY, STORAGE, REWATCHVALUE, DISCUSS, SELECTOR_NONE } selector = SELECTOR_NONE; enum { TAGS, COMMENTS, NONE } textarea = NONE; std::string textbuf; int ret = 1; for( ret = xmlTextReaderRead(reader.get()); ret == 1; ret = xmlTextReaderRead(reader.get()) ) { const std::string name = xmlchar_to_str(xmlTextReaderConstName (reader.get())); if (name == "input") { xmlStringUPtr type(xmlTextReaderGetAttribute(reader.get(), "type"_xml)); xmlStringUPtr attr_name(xmlTextReaderGetAttribute(reader.get(), "name"_xml)); xmlStringUPtr attr_value(xmlTextReaderGetAttribute(reader.get(), "value"_xml)); if (type) { if (xmlStrEqual(type.get(), "text"_xml) || xmlStrEqual(type.get(), "checkbox"_xml)) { if (xmlStrEqual(attr_name.get(), "fansub_group"_xml)) res->set_fansub_group(xmlchar_to_str(attr_value.get())); else if (xmlStrEqual(attr_name.get(), "list_downloaded_eps"_xml)) res->set_downloaded_items(xmlchar_to_str(attr_value.get())); else if (xmlStrEqual(attr_name.get(), "list_times_watched"_xml)) res->set_times_consumed(xmlchar_to_str(attr_value.get())); else if (xmlStrEqual(attr_name.get(), "storageVal"_xml)) res->set_storage_value(xmlchar_to_str(attr_value.get())); } } } else if (name == "textarea" && xmlTextReaderNodeType(reader.get()) == XML_READER_TYPE_ELEMENT) { xmlStringUPtr attr_name(xmlTextReaderGetAttribute(reader.get(), "name"_xml)); if (xmlStrEqual(attr_name.get(), "tags"_xml)) textarea = TAGS; else if (xmlStrEqual(attr_name.get(), "list_comments"_xml)) textarea = COMMENTS; else textarea = NONE; textbuf.clear(); } else if (name == "textarea" && xmlTextReaderNodeType(reader.get()) == XML_READER_TYPE_END_ELEMENT) { if (textarea != NONE) { switch (textarea) { case TAGS: /* Not a 'detailed' field */ break; case COMMENTS: res->set_comments(std::string(textbuf)); break; case NONE: default: break; } textarea = NONE; } } else if (name == "#text" && textarea != NONE) { textbuf.append(xmlchar_to_str(xmlTextReaderConstValue(reader.get()))); } else if (name == "select" && xmlTextReaderNodeType(reader.get()) == XML_READER_TYPE_ELEMENT) { xmlStringUPtr attr_name(xmlTextReaderGetAttribute(reader.get(), "name"_xml)); if (xmlStrEqual(attr_name.get(), "priority"_xml)) selector = PRIORITY; if (xmlStrEqual(attr_name.get(), "storage"_xml)) selector = STORAGE; if (xmlStrEqual(attr_name.get(), "list_rewatch_value"_xml)) selector = REWATCHVALUE; if (xmlStrEqual(attr_name.get(), "discuss"_xml)) selector = DISCUSS; } else if (name == "select" && xmlTextReaderNodeType(reader.get()) == XML_READER_TYPE_END_ELEMENT) { selector = SELECTOR_NONE; } else if (name == "option" && xmlTextReaderNodeType(reader.get()) == XML_READER_TYPE_ELEMENT) { xmlStringUPtr value(xmlTextReaderGetAttribute(reader.get(), "value"_xml)); if (xmlTextReaderMoveToAttribute(reader.get(), "selected"_xml) == 1) { switch (selector) { case PRIORITY: res->set_priority(xmlchar_to_str(value.get())); break; case STORAGE: res->set_storage_value(xmlchar_to_str(value.get())); break; case REWATCHVALUE: res->set_reconsume_value(xmlchar_to_str(value.get())); break; case DISCUSS: res->set_enable_discussion(xmlchar_to_str(value.get())); break; case SELECTOR_NONE: default: break; } } } } if (ret != 0) return nullptr; // Some sort of parsing error return res; }