static void exsltMathMaxFunction (xmlXPathParserContextPtr ctxt, int nargs) { xmlNodeSetPtr ns; double ret; void *user = NULL; if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { user = ctxt->value->user; ctxt->value->boolval = 0; ctxt->value->user = 0; } ns = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) return; ret = exsltMathMax(ns); xmlXPathFreeNodeSet(ns); if (user != NULL) xmlFreeNodeList((xmlNodePtr)user); xmlXPathReturnNumber(ctxt, ret); }
/** * exsltMathLowestFunction: * @ctxt: an XPath parser context * @nargs: the number of arguments * * Wraps #exsltMathLowest for use by the XPath processor */ static void exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) { xmlNodeSetPtr ns, ret; void *user = NULL; if (nargs != 1) { xmlXPathSetArityError(ctxt); return; } /* We need to delay the freeing of value->user */ if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { user = ctxt->value->user; ctxt->value->boolval = 0; ctxt->value->user = NULL; } ns = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) return; ret = exsltMathLowest(ns); xmlXPathFreeNodeSet(ns); if (user != NULL) xmlFreeNodeList((xmlNodePtr)user); xmlXPathReturnNodeSet(ctxt, ret); }
/** * exsltMathMinFunction: * @ctxt: an XPath parser context * @nargs: the number of arguments * * Wraps #exsltMathMin for use by the XPath processor. */ static void exsltMathMinFunction (xmlXPathParserContextPtr ctxt, int nargs) { xmlNodeSetPtr ns; double ret; void *user = NULL; if (nargs != 1) { xsltGenericError(xsltGenericErrorContext, "math:min: invalid number of arguments\n"); ctxt->error = XPATH_INVALID_ARITY; return; } /* We need to delay the freeing of value->user */ if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { user = ctxt->value->user; ctxt->value->boolval = 0; ctxt->value->user = NULL; } ns = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) return; ret = exsltMathMin(ns); xmlXPathFreeNodeSet(ns); if (user != NULL) xmlFreeNodeList((xmlNodePtr)user); xmlXPathReturnNumber(ctxt, ret); }
/** * xmlSecNodeSetDestroy: * @nset: the pointer to node set. * * Destroys the nodes set created with #xmlSecNodeSetCreate function. */ EXPORT_C void xmlSecNodeSetDestroy(xmlSecNodeSetPtr nset) { xmlSecNodeSetPtr tmp; xmlSecAssert(nset != NULL); while((tmp = nset) != NULL) { if((nset->next != NULL) && (nset->next != nset)) { nset->next->prev = nset->prev; nset->prev->next = nset->next; nset = nset->next; } else { nset = NULL; } if(tmp->nodes != NULL) { xmlXPathFreeNodeSet(tmp->nodes); } if(tmp->children != NULL) { xmlSecNodeSetDestroy(tmp->children); } if((tmp->doc != NULL) && (tmp->destroyDoc != 0)) { xmlFreeDoc(tmp->doc); } memset(tmp, 0, sizeof(xmlSecNodeSet)); xmlFree(tmp); } }
/** @arg n entry node * @arg len size of @a *s in bytes * @arg s pointer where result will be saved, error string on failure * @retval TRUE on success * @retval FALSE on error */ gboolean entry_orths_to_string(xmlNodePtr n, int len, char *s) { g_return_val_if_fail(n, FALSE); g_return_val_if_fail(s, FALSE); g_return_val_if_fail(len>0, FALSE); xmlDocPtr doc = copy_node_to_doc(n); // find the orth children of the current entry xmlNodeSetPtr set = find_node_set("/entry/form/orth", doc, NULL); if(!set || !set->nodeNr) { g_strlcpy(s, _("No nodes (form/orth)!"), len); if(set) xmlXPathFreeNodeSet(set); xmlFreeDoc(doc); return FALSE; } // alloc temporary buffer // if glib offered g_utf8_strlcat(), we would not need // this buffer char *e = (char *) g_malloc(len); e[0] = '\0'; int i; xmlNodePtr *n2; for(i=0, n2 = set->nodeTab; *n2 && i<set->nodeNr; n2++, i++) { xmlChar* content = xmlNodeGetContent(*n2); int l = strlen(e); if(l) g_strlcat(e, ", ", len); if(!content) g_strlcat(e, "(null)", len); else g_strlcat(e, (gchar *) content, len); if(content) xmlFree(content); } xmlXPathFreeNodeSet(set); // copy again, caring for utf8 chars longer than 1 byte g_utf8_strncpy(s, e, len/2); g_free(e); xmlFreeDoc(doc); return TRUE; }
bool NavigationTable::ParseXML(xmlNodePtr node) { if ( node == nullptr ) return false; string name(node->name); if ( AllowedRootNodeNames.find(name) == AllowedRootNodeNames.end() ) return false; _type = _getProp(node, "type", ePub3NamespaceURI); if ( _type.empty() ) return false; #if EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS) XPathWrangler xpath(node->doc, {{"epub", ePub3NamespaceURI}}); // goddamn I love C++11 initializer list constructors #else XPathWrangler::NamespaceList __ns; __ns["epub"] = ePub3NamespaceURI; XPathWrangler xpath(node->doc, __ns); #endif xpath.NameDefaultNamespace("html"); // look for optional <h2> title // Q: Should we fail on finding multiple <h2> tags here? auto strings = xpath.Strings("./html:h2[1]/text()", node); if ( !strings.empty() ) _title = std::move(strings[0]); // load List Elements from a single Ordered List // first: confirm there's a single list xmlNodeSetPtr nodes = xpath.Nodes("./html:ol", node); if ( nodes == nullptr ) return false; if ( nodes->nodeNr != 1 ) { xmlXPathFreeNodeSet(nodes); return false; } LoadChildElements(std::enable_shared_from_this<NavigationTable>::shared_from_this(), nodes->nodeTab[0]); xmlXPathFreeNodeSet(nodes); return true; }
xmlNodePtr getXNode(xmlXPathContextPtr context, const gchar *xpath) { xmlNodeSetPtr set = getXNodes(context, xpath); xmlNodePtr ret = NULL; if(!xmlXPathNodeSetIsEmpty(set)) ret = set->nodeTab[0]; xmlXPathFreeNodeSet(set); return ret; }
static int xmlSecTransformVisa3DHackExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { xmlChar** idPtr; xmlDocPtr doc; xmlAttrPtr attr; xmlNodeSetPtr nodeSet; xmlSecAssert2(xmlSecTransformVisa3DHackCheckId(transform), -1); xmlSecAssert2(transform->outNodes == NULL, -1); xmlSecAssert2(last != 0, -1); xmlSecAssert2(transformCtx != NULL, -1); idPtr = xmlSecVisa3DHackTransformGetIDPtr(transform); xmlSecAssert2(idPtr != NULL, -1); xmlSecAssert2((*idPtr) != NULL, -1); doc = (transform->inNodes != NULL) ? transform->inNodes->doc : transform->hereNode->doc; xmlSecAssert2(doc != NULL, -1); attr = xmlGetID(doc, (*idPtr)); if((attr == NULL) || (attr->parent == NULL)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlGetID", XMLSEC_ERRORS_R_XML_FAILED, "id=\"%s\"", xmlSecErrorsSafeString((*idPtr))); return(-1); } nodeSet = xmlXPathNodeSetCreate(attr->parent); if(nodeSet == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlXPathNodeSetCreate", XMLSEC_ERRORS_R_XML_FAILED, "id=\"%s\"", xmlSecErrorsSafeString((*idPtr))); return(-1); } transform->outNodes = xmlSecNodeSetCreate(doc, nodeSet, xmlSecNodeSetTreeWithoutComments); if(transform->outNodes == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecNodeSetCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlXPathFreeNodeSet(nodeSet); return(-1); } return(0); }
xmlNodePtr find_single_node(const char *xpath, const xmlDocPtr doc) { xmlNodeSetPtr nodes = find_node_set(xpath, doc, NULL); if(!nodes) return NULL; if(nodes->nodeNr>1) g_printerr(_("%s: %i matching nodes (only 1 expected). Taking first.\n"), G_STRLOC, nodes->nodeNr); xmlNodePtr bodyNode = *(nodes->nodeTab); xmlXPathFreeNodeSet(nodes); return bodyNode; }
bool NavigationTable::Parse(xmlNodePtr node) { if ( node == nullptr ) return false; string name(node->name); if ( AllowedRootNodeNames.find(name) == AllowedRootNodeNames.end() ) return false; _type = _getProp(node, "type", ePub3NamespaceURI); if ( _type.empty() ) return false; XPathWrangler xpath(node->doc, {{"epub", ePub3NamespaceURI}}); // goddamn I love C++11 initializer list constructors xpath.NameDefaultNamespace("html"); // look for optional <h2> title // Q: Should we fail on finding multiple <h2> tags here? auto strings = xpath.Strings("./html:h2[1]/text()", node); if ( !strings.empty() ) _title = std::move(strings[0]); // load List Elements from a single Ordered List // first: confirm there's a single list xmlNodeSetPtr nodes = xpath.Nodes("./html:ol", node); if ( nodes == nullptr ) return false; if ( nodes->nodeNr != 1 ) { xmlXPathFreeNodeSet(nodes); return false; } LoadChildElements(this, nodes->nodeTab[0]); xmlXPathFreeNodeSet(nodes); return true; }
static void load_shapefiles() { if (shapefiles || shapefileIds) return; xmlDoc *doc; xmlXPathContext* xpath; doc = xmlReadFile(darxen_file_support_get_overridable_file_path("Shapefiles.xml"), NULL, 0); if (!doc) { g_warning("Unable to load default shapefiles"); return; } xpath = xmlXPathNewContext(doc); if (!xpath) { xmlFreeDoc(doc); g_warning("Unable to load default shapefiles"); return; } int idCount; char** ids = darxen_xml_get_strs(xpath, "/Shapefiles/Shapefile/@id", &idCount); int i; for (i = 0; i < idCount; i++) { shapefileIds = g_slist_prepend(shapefileIds, ids[1]); gchar* expr = darxen_xml_path_format("/Shapefiles/Shapefile[@id=\"%s\"]", ids[i]); xmlNodeSet* nodes = darxen_xml_get_nodes(xpath, expr); g_free(expr); g_assert(nodes->nodeNr == 1); DarxenShapefile* shapefile = darxen_shapefiles_load_config(nodes->nodeTab[0], NULL); shapefiles = g_list_prepend(shapefiles, shapefile); xmlXPathFreeNodeSet(nodes); } free(ids); shapefileIds = g_slist_reverse(shapefileIds); shapefiles = g_list_reverse(shapefiles); xmlXPathFreeContext(xpath); xmlFreeDoc(doc); }
bool CSpmXml::PopQuery() { if (0 == m_lstSets.size()) return false; if (m_pCurNodeSet) xmlXPathFreeNodeSet(m_pCurNodeSet); CNodeSet& nodeset = m_lstSets.back(); m_pCurNodeSet = nodeset.set; m_nCurItem = nodeset.cur; m_lstSets.pop_back(); return true; }
xmlNodePtr CSpmXml::MoveFirst(const QString& strXPathQuery, xmlNodePtr pParent, int* pnCount) { if (strXPathQuery.isEmpty()) return 0; pParent = GetNode(pParent); if (0 == pParent) return 0; QString strQuery; if (strXPathQuery.left(2) != "//") // локальный запрос { strQuery = (char *)xmlGetNodePath(pParent); strQuery += strXPathQuery; } else strQuery = strXPathQuery; xmlXPathContextPtr pContext = xmlXPathNewContext(m_pXMLDoc); if (0 == pContext) return 0; xmlXPathObjectPtr pQuery = xmlXPathEvalExpression(BAD_CAST strQuery.toUtf8().data(), pContext); xmlXPathFreeContext(pContext); if (0 == pQuery) return 0; if (m_pCurNodeSet) { xmlXPathFreeNodeSet(m_pCurNodeSet); m_pCurNodeSet = 0; } m_nCurItem = 0; m_pCurNodeSet = pQuery->nodesetval; if (0 == m_pCurNodeSet) return 0; if (pnCount) *pnCount = m_pCurNodeSet->nodeNr; if (0 == m_pCurNodeSet->nodeNr) return 0; m_pCurNode = m_pCurNodeSet->nodeTab[m_nCurItem]; return m_pCurNode; }
/* * Load preferences. */ static void gdisp_loadPreferences ( Kernel_T *kernel, xmlDoc *document ) { xmlNodeSet *preferenceTableNode = (xmlNodeSet*)NULL; xmlNode *preferenceNode = (xmlNode*)NULL; xmlChar *propertyValue = (xmlChar*)NULL; unsigned int cptPreference = 0; /* * Get back information. */ preferenceTableNode = gdisp_xmlGetChildren(document,(xmlNode*)NULL, BAD_CAST "//Preferences/preference"); if (preferenceTableNode != (xmlNodeSet*)NULL && preferenceTableNode->nodeNr > 0) { for (cptPreference=0; cptPreference<preferenceTableNode->nodeNr; cptPreference++) { preferenceNode = preferenceTableNode->nodeTab[cptPreference]; propertyValue = xmlGetProp(preferenceNode, preferenceNode->properties->name); gdisp_setUpPreferenceFromString(kernel, (gchar*)preferenceNode->properties->name, (gchar*)propertyValue); xmlFree(propertyValue); } } /* * Free node set. */ xmlXPathFreeNodeSet(preferenceTableNode); }
/** * xmlSecNodeSetGetChildren: * @doc: the pointer to an XML document. * @parent: the pointer to parent XML node or NULL if we want to include all document nodes. * @withComments: the flag include comments or not. * @invert: the "invert" flag. * * Creates a new nodes set that contains: * - if @withComments is not 0 and @invert is 0: * all nodes in the @parent subtree; * - if @withComments is 0 and @invert is 0: * all nodes in the @parent subtree except comment nodes; * - if @withComments is not 0 and @invert not is 0: * all nodes in the @doc except nodes in the @parent subtree; * - if @withComments is 0 and @invert is 0: * all nodes in the @doc except nodes in the @parent subtree * and comment nodes. * * Returns pointer to the newly created #xmlSecNodeSet structure * or NULL if an error occurs. */ EXPORT_C xmlSecNodeSetPtr xmlSecNodeSetGetChildren(xmlDocPtr doc, const xmlNodePtr parent, int withComments, int invert) { xmlNodeSetPtr nodes; xmlSecNodeSetType type; xmlSecNodeSetPtr result = NULL; xmlSecAssert2(doc != NULL, NULL); nodes = xmlXPathNodeSetCreate(parent); if(nodes == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlXPathNodeSetCreate", XMLSEC_ERRORS_R_XML_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } /* if parent is NULL then we add all the doc children */ if(parent == NULL) { xmlNodePtr cur; for(cur = doc->children; cur != NULL; cur = cur->next) { if(withComments || (cur->type != XML_COMMENT_NODE)) { xmlXPathNodeSetAdd(nodes, cur); } } } if(withComments && invert) { type = xmlSecNodeSetTreeInvert; } else if(withComments && !invert) { type = xmlSecNodeSetTree; } else if(!withComments && invert) { type = xmlSecNodeSetTreeWithoutCommentsInvert; } else { /* if(!withComments && !invert) */ type = xmlSecNodeSetTreeWithoutComments; } result = xmlSecNodeSetCreate(doc, nodes, type); if ( !result ) { xmlXPathFreeNodeSet( nodes ); } return result; }
void NavigationTable::LoadChildElements(NavigationElement *pElement, xmlNodePtr olNode) { XPathWrangler xpath(olNode->doc, {{"epub", ePub3NamespaceURI}}); xpath.NameDefaultNamespace("html"); xmlNodeSetPtr liNodes = xpath.Nodes("./html:li", olNode); for ( size_t i = 0; i < liNodes->nodeNr; i++ ) { NavigationElement* childElement = BuildNavigationPoint(liNodes->nodeTab[i]); if(childElement != nullptr) { pElement->AppendChild(childElement); } } xmlXPathFreeNodeSet(liNodes); }
bool CSpmXml::DeleteNodes(const QString& strXPathQuery, xmlNodePtr pParent) { if (strXPathQuery.isEmpty()) return false; pParent = GetNode(pParent); if (0 == pParent) return false; QString strQuery; if (strXPathQuery.left(2) != "//") // локальный запрос { strQuery = (char *)xmlGetNodePath(pParent); strQuery += strXPathQuery; } else strQuery = strXPathQuery; xmlXPathContextPtr pContext = xmlXPathNewContext(m_pXMLDoc); if (0 == pContext) return false; xmlXPathObjectPtr pQuery = xmlXPathEvalExpression(BAD_CAST strQuery.toUtf8().data(), pContext); xmlXPathFreeContext(pContext); if (0 == pQuery) return false; xmlNodeSetPtr pNodeSet = pQuery->nodesetval; if ((0 == pNodeSet) || (0 == pNodeSet->nodeNr)) return false; for (int i = 0; i < pNodeSet->nodeNr; i++) { xmlNodePtr pNode = pNodeSet->nodeTab[i]; xmlUnlinkNode(pNode); SetModified(); } xmlXPathFreeNodeSet(pNodeSet); return true; }
NavigationList PackageBase::NavTablesFromManifestItem(shared_ptr<PackageBase> owner, shared_ptr<ManifestItem> pItem) { PackagePtr sharedPkg = std::dynamic_pointer_cast<Package>(owner); if ( !sharedPkg ) return NavigationList(); if ( pItem == nullptr ) return NavigationList(); xmlDocPtr doc = pItem->ReferencedDocument(); if ( doc == nullptr ) return NavigationList(); // find each <nav> node #if EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS) XPathWrangler xpath(doc, {{"epub", ePub3NamespaceURI}}); // goddamn I love C++11 initializer list constructors #else XPathWrangler::NamespaceList __m; __m["epub"] = ePub3NamespaceURI; XPathWrangler xpath(doc, __m); #endif xpath.NameDefaultNamespace("html"); xmlNodeSetPtr nodes = xpath.Nodes("//html:nav"); NavigationList tables; for ( int i = 0; i < nodes->nodeNr; i++ ) { xmlNodePtr navNode = nodes->nodeTab[i]; auto navTablePtr = std::make_shared<class NavigationTable>(sharedPkg, pItem->Href()); if ( navTablePtr->ParseXML(navNode) ) tables.push_back(navTablePtr); } xmlXPathFreeNodeSet(nodes); // now look for any <dl> nodes with an epub:type of "glossary" nodes = xpath.Nodes("//html:dl[epub:type='glossary']"); return tables; }
void Container::LoadEncryption() { ContainerPtr sharedThis(shared_from_this()); unique_ptr<ArchiveReader> pZipReader = _archive->ReaderAtPath(gEncryptionFilePath); if ( !pZipReader ) return; ArchiveXmlReader reader(std::move(pZipReader)); xmlDocPtr enc = reader.xmlReadDocument(gEncryptionFilePath, nullptr, XML_PARSE_RECOVER|XML_PARSE_NOENT|XML_PARSE_DTDATTR); if ( enc == nullptr ) return; #if EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS) XPathWrangler xpath(enc, {{"enc", XMLENCNamespaceURI}, {"ocf", OCFNamespaceURI}}); #else XPathWrangler::NamespaceList __ns; __ns["ocf"] = OCFNamespaceURI; __ns["enc"] = XMLENCNamespaceURI; XPathWrangler xpath(enc, __ns); #endif xmlNodeSetPtr nodes = xpath.Nodes("/ocf:encryption/enc:EncryptedData"); if ( nodes == nullptr || nodes->nodeNr == 0 ) { xmlChar* mem = nullptr; int size = 0; xmlDocDumpMemory(enc, &mem, &size); printf("%s\n", reinterpret_cast<char*>(mem)); xmlFree(mem); return; // should be a hard error? } for ( int i = 0; i < nodes->nodeNr; i++ ) { auto encPtr = std::make_shared<EncryptionInfo>(sharedThis); if ( encPtr->ParseXML(nodes->nodeTab[i]) ) _encryption.push_back(encPtr); } xmlXPathFreeNodeSet(nodes); }
xmlNodePtr CSpmXml::MoveNext() { if (0 == m_pXMLDoc) return 0; if (0 == m_pCurNodeSet) return 0; m_nCurItem++; if (m_nCurItem < m_pCurNodeSet->nodeNr) { m_pCurNode = m_pCurNodeSet->nodeTab[m_nCurItem]; return m_pCurNode; } else { xmlXPathFreeNodeSet(m_pCurNodeSet); m_pCurNodeSet = 0; m_nCurItem = 0; return 0; } }
void Container::LoadEncryption() { ArchiveReader *pZipReader = _archive->ReaderAtPath(gEncryptionFilePath); if ( pZipReader == nullptr ) return; ArchiveXmlReader reader(pZipReader); xmlDocPtr enc = reader.xmlReadDocument(gEncryptionFilePath, nullptr, XML_PARSE_RECOVER|XML_PARSE_NOENT|XML_PARSE_DTDATTR); if ( enc == nullptr ) return; XPathWrangler xpath(enc, {{"enc", XMLENCNamespaceURI}, {"ocf", OCFNamespaceURI}}); xmlNodeSetPtr nodes = xpath.Nodes("/ocf:encryption/enc:EncryptedData"); if ( nodes == nullptr || nodes->nodeNr == 0 ) return; // should be a hard error? for ( size_t i = 0; i < nodes->nodeNr; i++ ) { _encryption.emplace_back(new EncryptionInfo(nodes->nodeTab[i])); } xmlXPathFreeNodeSet(nodes); }
void NavigationTable::LoadChildElements(shared_ptr<NavigationElement> pElement, xmlNodePtr olNode) { #if EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS) XPathWrangler xpath(olNode->doc, {{"epub", ePub3NamespaceURI}}); #else XPathWrangler::NamespaceList __ns; __ns["ePub3"] = ePub3NamespaceURI; XPathWrangler xpath(olNode->doc, __ns); #endif xpath.NameDefaultNamespace("html"); xmlNodeSetPtr liNodes = xpath.Nodes("./html:li", olNode); for ( int i = 0; i < liNodes->nodeNr; i++ ) { auto childElement = BuildNavigationPoint(liNodes->nodeTab[i]); if ( childElement ) { pElement->AppendChild(childElement); } } xmlXPathFreeNodeSet(liNodes); }
static void xsltp_extension_string_join(xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *ret = NULL, *sep = NULL, *str = NULL; xmlNodeSetPtr nodeSet = NULL; int i, j; if (nargs < 2) { xmlXPathSetArityError(ctxt); return; } if (xmlXPathStackIsNodeSet(ctxt)) { xmlXPathSetTypeError(ctxt); return; } sep = xmlXPathPopString(ctxt); for (i = 1; i < nargs; i++) { if (!xmlXPathStackIsNodeSet(ctxt)) { str = xmlXPathPopString(ctxt); if (i == 1) { ret = str; } else { str = xmlStrcat(str, sep); str = xmlStrcat(str, ret); xmlFree(ret); ret = str; } } else { nodeSet = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { xmlXPathSetTypeError(ctxt); goto fail; } for (j = nodeSet->nodeNr - 1; j >= 0; j--) { str = xmlXPathCastNodeToString(nodeSet->nodeTab[j]); if (i == 1 && j == (nodeSet->nodeNr - 1)) { ret = str; } else { str = xmlStrcat(str, sep); str = xmlStrcat(str, ret); xmlFree(ret); ret = str; } } xmlXPathFreeNodeSet(nodeSet); } } xmlXPathReturnString(ctxt, ret); fail: if (sep != NULL) xmlFree(sep); }
/** * 'update' operation */ static void edUpdate(xmlDocPtr doc, xmlNodeSetPtr nodes, const char *val, XmlNodeType type, xmlXPathContextPtr ctxt) { int i; xmlXPathCompExprPtr xpath = NULL; if (type == XML_EXPR) { xpath = xmlXPathCompile((const xmlChar*) val); if (!xpath) return; } for (i = 0; i < nodes->nodeNr; i++) { /* update node */ if (type == XML_EXPR) { xmlXPathObjectPtr res; ctxt->node = nodes->nodeTab[i]; res = xmlXPathCompiledEval(xpath, ctxt); if (res->type == XPATH_NODESET || res->type == XPATH_XSLT_TREE) { int j; xmlNodePtr oldChild; xmlNodeSetPtr oldChildren = xmlXPathNodeSetCreate(NULL); /* NOTE: newChildren can be NULL for empty result set */ xmlNodeSetPtr newChildren = res->nodesetval; /* NOTE: nodes can be both oldChildren and newChildren */ /* unlink the old children */ for (oldChild = nodes->nodeTab[i]->children; oldChild; oldChild = oldChild->next) { xmlUnlinkNode(oldChild); /* we can't free it now because an oldChild can also be newChild! just put it in the list */ xmlXPathNodeSetAdd(oldChildren, oldChild); } /* add the new children */ for (j = 0; newChildren && j < newChildren->nodeNr; j++) { xmlNodePtr node = newChildren->nodeTab[j]; xmlAddChild(nodes->nodeTab[i], /* if node is linked to this doc we need to copy */ (node->doc == doc)? xmlDocCopyNode(node, doc, 1) : node); newChildren->nodeTab[j] = NULL; } newChildren->nodeNr = 0; /* NOTE: if any oldChildren were newChildren, they've been copied so we can free them all now */ for (j = 0; j < oldChildren->nodeNr; j++) { xmlFreeNode(oldChildren->nodeTab[j]); oldChildren->nodeTab[j] = NULL; } oldChildren->nodeNr = 0; xmlXPathFreeNodeSet(oldChildren); } else { res = xmlXPathConvertString(res); update_string(doc, nodes->nodeTab[i], res->stringval); } xmlXPathFreeObject(res); } else { update_string(doc, nodes->nodeTab[i], (const xmlChar*) val); } } xmlXPathFreeCompExpr(xpath); }
bool Package::Unpack() { PackagePtr sharedMe = shared_from_this(); // very basic sanity check xmlNodePtr root = xmlDocGetRootElement(_opf); string rootName(reinterpret_cast<const char*>(root->name)); rootName.tolower(); if ( rootName != "package" ) { HandleError(EPUBError::OPFInvalidPackageDocument); return false; // not an OPF file, innit? } if ( _getProp(root, "version").empty() ) { HandleError(EPUBError::OPFPackageHasNoVersion); } InstallPrefixesFromAttributeValue(_getProp(root, "prefix", ePub3NamespaceURI)); // go through children to determine the CFI index of the <spine> tag static const xmlChar* kSpineName = BAD_CAST "spine"; static const xmlChar* kManifestName = BAD_CAST "manifest"; static const xmlChar* kMetadataName = BAD_CAST "metadata"; _spineCFIIndex = 0; uint32_t idx = 0; xmlNodePtr child = xmlFirstElementChild(root); while ( child != nullptr ) { idx += 2; if ( xmlStrEqual(child->name, kSpineName) ) { _spineCFIIndex = idx; if ( _spineCFIIndex != 6 ) HandleError(EPUBError::OPFSpineOutOfOrder); } else if ( xmlStrEqual(child->name, kManifestName) && idx != 4 ) { HandleError(EPUBError::OPFManifestOutOfOrder); } else if ( xmlStrEqual(child->name, kMetadataName) && idx != 2 ) { HandleError(EPUBError::OPFMetadataOutOfOrder); } child = xmlNextElementSibling(child); } if ( _spineCFIIndex == 0 ) { HandleError(EPUBError::OPFNoSpine); return false; // spineless! } #if EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS) XPathWrangler xpath(_opf, {{"opf", OPFNamespace}, {"dc", DCNamespace}}); #else XPathWrangler::NamespaceList __m; __m["opf"] = OPFNamespace; __m["dc"] = DCNamespace; XPathWrangler xpath(_opf, __m); #endif // simple things: manifest and spine items xmlNodeSetPtr manifestNodes = nullptr; xmlNodeSetPtr spineNodes = nullptr; try { manifestNodes = xpath.Nodes("/opf:package/opf:manifest/opf:item"); spineNodes = xpath.Nodes("/opf:package/opf:spine/opf:itemref"); if ( manifestNodes == nullptr ) { HandleError(EPUBError::OPFNoManifestItems); } if ( spineNodes == nullptr ) { HandleError(EPUBError::OPFNoSpineItems); } for ( int i = 0; i < manifestNodes->nodeNr; i++ ) { auto p = std::make_shared<ManifestItem>(sharedMe); if ( p->ParseXML(p, manifestNodes->nodeTab[i]) ) { #if EPUB_HAVE(CXX_MAP_EMPLACE) _manifest.emplace(p->Identifier(), p); #else _manifest[p->Identifier()] = p; #endif StoreXMLIdentifiable(p); } else { // TODO: Need an error here } } // check fallback chains typedef std::map<string, bool> IdentSet; IdentSet idents; for ( auto &pair : _manifest ) { ManifestItemPtr item = pair.second; if ( item->FallbackID().empty() ) continue; idents[item->XMLIdentifier()] = true; while ( !item->FallbackID().empty() ) { if ( idents[item->FallbackID()] ) { HandleError(EPUBError::OPFFallbackChainCircularReference); break; } item = item->Fallback(); } idents.clear(); } SpineItemPtr cur; for ( int i = 0; i < spineNodes->nodeNr; i++ ) { auto next = std::make_shared<SpineItem>(sharedMe); if ( next->ParseXML(next, spineNodes->nodeTab[i]) == false ) { // TODO: need an error code here continue; } // validation of idref auto manifestFound = _manifest.find(next->Idref()); if ( manifestFound == _manifest.end() ) { HandleError(EPUBError::OPFInvalidSpineIdref, _Str(next->Idref(), " does not correspond to a manifest item")); continue; } // validation of spine resource type w/fallbacks ManifestItemPtr manifestItem = next->ManifestItem(); bool isContentDoc = false; do { if ( manifestItem->MediaType() == "application/xhtml+xml" || manifestItem->MediaType() == "image/svg" ) { isContentDoc = true; break; } } while ( (manifestItem = manifestItem->Fallback()) ); if ( !isContentDoc ) HandleError(EPUBError::OPFFallbackChainHasNoContentDocument); StoreXMLIdentifiable(next); if ( cur != nullptr ) { cur->SetNextItem(next); } else { _spine = next; } cur = next; } } catch (const std::system_error& exc) { if ( manifestNodes != nullptr ) xmlXPathFreeNodeSet(manifestNodes); if ( spineNodes != nullptr ) xmlXPathFreeNodeSet(spineNodes); if ( exc.code().category() == epub_spec_category() ) throw; return false; } catch (...) { if ( manifestNodes != nullptr ) xmlXPathFreeNodeSet(manifestNodes); if ( spineNodes != nullptr ) xmlXPathFreeNodeSet(spineNodes); return false; } xmlXPathFreeNodeSet(manifestNodes); xmlXPathFreeNodeSet(spineNodes); // now the metadata, which is slightly more involved due to extensions xmlNodeSetPtr metadataNodes = nullptr; xmlNodeSetPtr refineNodes = xmlXPathNodeSetCreate(nullptr); try { shared_ptr<PropertyHolder> holderPtr = std::dynamic_pointer_cast<PropertyHolder>(sharedMe); metadataNodes = xpath.Nodes("/opf:package/opf:metadata/*"); if ( metadataNodes == nullptr ) HandleError(EPUBError::OPFNoMetadata); bool foundIdentifier = false, foundTitle = false, foundLanguage = false, foundModDate = false; string uniqueIDRef = _getProp(root, "unique-identifier"); if ( uniqueIDRef.empty() ) HandleError(EPUBError::OPFPackageUniqueIDInvalid); for ( int i = 0; i < metadataNodes->nodeNr; i++ ) { xmlNodePtr node = metadataNodes->nodeTab[i]; PropertyPtr p; if ( node->ns != nullptr && xmlStrcmp(node->ns->href, BAD_CAST DCNamespace) == 0 ) { // definitely a main node p = std::make_shared<Property>(holderPtr); } else if ( _getProp(node, "name").size() > 0 ) { // it's an ePub2 item-- ignore it continue; } else if ( _getProp(node, "refines").empty() ) { // not refining anything, so it's a main node p = std::make_shared<Property>(holderPtr); } else { // by elimination it's refining something-- we'll process it later when we know we've got all the main nodes in there xmlXPathNodeSetAdd(refineNodes, node); } if ( p && p->ParseMetaElement(node) ) { switch ( p->Type() ) { case DCType::Identifier: { foundIdentifier = true; if ( !uniqueIDRef.empty() && uniqueIDRef != p->XMLIdentifier() ) HandleError(EPUBError::OPFPackageUniqueIDInvalid); break; } case DCType::Title: { foundTitle = true; break; } case DCType::Language: { foundLanguage = true; break; } case DCType::Custom: { if ( p->PropertyIdentifier() == MakePropertyIRI("modified", "dcterms") ) foundModDate = true; break; } default: break; } AddProperty(p); StoreXMLIdentifiable(p); } } if ( !foundIdentifier ) HandleError(EPUBError::OPFMissingIdentifierMetadata); if ( !foundTitle ) HandleError(EPUBError::OPFMissingTitleMetadata); if ( !foundLanguage ) HandleError(EPUBError::OPFMissingLanguageMetadata); if ( !foundModDate ) HandleError(EPUBError::OPFMissingModificationDateMetadata); for ( int i = 0; i < refineNodes->nodeNr; i++ ) { xmlNodePtr node = refineNodes->nodeTab[i]; string ident = _getProp(node, "refines"); if ( ident.empty() ) { HandleError(EPUBError::OPFInvalidRefinementAttribute, "Empty IRI for 'refines' attribute"); continue; } if ( ident[0] == '#' ) { ident = ident.substr(1); } else { // validation only right now IRI iri(ident); if ( iri.IsEmpty() ) { HandleError(EPUBError::OPFInvalidRefinementAttribute, _Str("#", ident, " is not a valid IRI")); } else if ( iri.IsRelative() == false ) { HandleError(EPUBError::OPFInvalidRefinementAttribute, _Str(iri.IRIString(), " is not a relative IRI")); } continue; } auto found = _xmlIDLookup.find(ident); if ( found == _xmlIDLookup.end() ) { HandleError(EPUBError::OPFInvalidRefinementTarget, _Str("#", ident, " does not reference an item in this document")); continue; } PropertyPtr prop = std::dynamic_pointer_cast<Property>(found->second); if ( prop ) { // it's a property, so this is an extension PropertyExtensionPtr extPtr = std::make_shared<PropertyExtension>(prop); if ( extPtr->ParseMetaElement(node) ) prop->AddExtension(extPtr); } else { // not a property, so treat this as a plain property shared_ptr<PropertyHolder> ptr = std::dynamic_pointer_cast<PropertyHolder>(found->second); if ( ptr ) { prop = std::make_shared<Property>(ptr); if ( prop->ParseMetaElement(node) ) ptr->AddProperty(prop); } } } // now look at the <spine> element for properties xmlNodePtr spineNode = xmlFirstElementChild(root); for ( uint32_t i = 2; i < _spineCFIIndex; i += 2 ) spineNode = xmlNextElementSibling(spineNode); string value = _getProp(spineNode, "page-progression-direction"); if ( !value.empty() ) { PropertyPtr prop = std::make_shared<Property>(holderPtr); prop->SetPropertyIdentifier(MakePropertyIRI("page-progression-direction")); prop->SetValue(value); AddProperty(prop); } } catch (std::system_error& exc) { if ( metadataNodes != nullptr ) xmlXPathFreeNodeSet(metadataNodes); if ( refineNodes != nullptr ) xmlXPathFreeNodeSet(refineNodes); if ( exc.code().category() == epub_spec_category() ) throw; return false; } catch (...) { if ( metadataNodes != nullptr ) xmlXPathFreeNodeSet(metadataNodes); if ( refineNodes != nullptr ) xmlXPathFreeNodeSet(refineNodes); return false; } xmlXPathFreeNodeSet(metadataNodes); xmlXPathFreeNodeSet(refineNodes); // now any content type bindings xmlNodeSetPtr bindingNodes = nullptr; try { bindingNodes = xpath.Nodes("/opf:package/opf:bindings/*"); if ( bindingNodes != nullptr ) { for ( int i = 0; i < bindingNodes->nodeNr; i++ ) { xmlNodePtr node = bindingNodes->nodeTab[i]; if ( xmlStrcasecmp(node->name, MediaTypeElementName) != 0 ) continue; //////////////////////////////////////////////////////////// // ePub Publications 3.0 §3.4.16: The `mediaType` Element // The media-type attribute is required. string mediaType = _getProp(node, "media-type"); if ( mediaType.empty() ) { HandleError(EPUBError::OPFBindingHandlerNoMediaType); throw false; } // Each child mediaType of a bindings element must define a unique // content type in its media-type attribute, and the media type // specified must not be a Core Media Type. if ( _contentHandlers[mediaType].empty() == false ) { // user shouldn't have added manual things yet, but for safety we'll look anyway for ( auto ptr : _contentHandlers[mediaType] ) { if ( typeid(*ptr) == typeid(MediaHandler) ) { HandleError(EPUBError::OPFMultipleBindingsForMediaType); } } } if ( CoreMediaTypes.find(mediaType) != CoreMediaTypes.end() ) { HandleError(EPUBError::OPFCoreMediaTypeBindingEncountered); } // The handler attribute is required string handlerID = _getProp(node, "handler"); if ( handlerID.empty() ) { HandleError(EPUBError::OPFBindingHandlerNotFound); } // The required handler attribute must reference the ID [XML] of an // item in the manifest of the default implementation for this media // type. The referenced item must be an XHTML Content Document. ManifestItemPtr handlerItem = ManifestItemWithID(handlerID); if ( !handlerItem ) { HandleError(EPUBError::OPFBindingHandlerNotFound); } if ( handlerItem->MediaType() != "application/xhtml+xml" ) { HandleError(EPUBError::OPFBindingHandlerInvalidType, _Str("Media handlers must be XHTML content documents, but referenced item has type '", handlerItem->MediaType(), "'.")); } // All XHTML Content Documents designated as handlers must have the // `scripted` property set in their manifest item's `properties` // attribute. if ( handlerItem->HasProperty(ItemProperties::HasScriptedContent) == false ) { HandleError(EPUBError::OPFBindingHandlerNotScripted); } // all good-- install it now _contentHandlers[mediaType].push_back(std::make_shared<MediaHandler>(sharedMe, mediaType, handlerItem->AbsolutePath())); } } } catch (std::exception& exc) { std::cerr << "Exception processing OPF file: " << exc.what() << std::endl; if ( bindingNodes != nullptr ) xmlXPathFreeNodeSet(bindingNodes); throw; } catch (...) { if ( bindingNodes != nullptr ) xmlXPathFreeNodeSet(bindingNodes); return false; } xmlXPathFreeNodeSet(bindingNodes); // now the navigation tables for ( auto item : _manifest ) { if ( !item.second->HasProperty(ItemProperties::Navigation) ) continue; NavigationList tables = NavTablesFromManifestItem(sharedMe, item.second); for ( auto table : tables ) { // have to dynamic_cast these guys to get the right pointer type shared_ptr<class NavigationTable> navTable = std::dynamic_pointer_cast<class NavigationTable>(table); #if EPUB_HAVE(CXX_MAP_EMPLACE) _navigation.emplace(navTable->Type(), navTable); #else _navigation[navTable->Type()] = navTable; #endif } } // lastly, let's set the media support information InitMediaSupport(); return true; }
/** * exsltStrReplaceFunction: * @ctxt: an XPath parser context * @nargs: the number of arguments * * Takes a string, and two node sets and returns the string with all strings in * the first node set replaced by all strings in the second node set. */ static void exsltStrReplaceFunction (xmlXPathParserContextPtr ctxt, int nargs) { int i, i_empty, n, slen0, rlen0, *slen, *rlen; void *mem = NULL; const xmlChar *src, *start; xmlChar *string, *search_str = NULL, *replace_str = NULL; xmlChar **search, **replace; xmlNodeSetPtr search_set = NULL, replace_set = NULL; xmlBufferPtr buf; if (nargs != 3) { xmlXPathSetArityError(ctxt); return; } /* get replace argument */ if (!xmlXPathStackIsNodeSet(ctxt)) replace_str = xmlXPathPopString(ctxt); else replace_set = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) goto fail_replace; /* get search argument */ if (!xmlXPathStackIsNodeSet(ctxt)) { search_str = xmlXPathPopString(ctxt); n = 1; } else { search_set = xmlXPathPopNodeSet(ctxt); n = search_set != NULL ? search_set->nodeNr : 0; } if (xmlXPathCheckError(ctxt)) goto fail_search; /* get string argument */ string = xmlXPathPopString(ctxt); if (xmlXPathCheckError(ctxt)) goto fail_string; /* check for empty search node list */ if (n <= 0) { exsltStrReturnString(ctxt, string, xmlStrlen(string)); goto done_empty_search; } /* allocate memory for string pointer and length arrays */ if (n == 1) { search = &search_str; replace = &replace_str; slen = &slen0; rlen = &rlen0; } else { mem = xmlMalloc(2 * n * (sizeof(const xmlChar *) + sizeof(int))); if (mem == NULL) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); goto fail_malloc; } search = (xmlChar **) mem; replace = search + n; slen = (int *) (replace + n); rlen = slen + n; } /* process arguments */ i_empty = -1; for (i=0; i<n; ++i) { if (search_set != NULL) { search[i] = xmlXPathCastNodeToString(search_set->nodeTab[i]); if (search[i] == NULL) { n = i; goto fail_process_args; } } slen[i] = xmlStrlen(search[i]); if (i_empty < 0 && slen[i] == 0) i_empty = i; if (replace_set != NULL) { if (i < replace_set->nodeNr) { replace[i] = xmlXPathCastNodeToString(replace_set->nodeTab[i]); if (replace[i] == NULL) { n = i + 1; goto fail_process_args; } } else replace[i] = NULL; } else { if (i == 0) replace[i] = replace_str; else replace[i] = NULL; } if (replace[i] == NULL) rlen[i] = 0; else rlen[i] = xmlStrlen(replace[i]); } if (i_empty >= 0 && rlen[i_empty] == 0) i_empty = -1; /* replace operation */ buf = xmlBufferCreate(); if (buf == NULL) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); goto fail_buffer; } src = string; start = string; while (*src != 0) { int max_len = 0, i_match = 0; for (i=0; i<n; ++i) { if (*src == search[i][0] && slen[i] > max_len && xmlStrncmp(src, search[i], slen[i]) == 0) { i_match = i; max_len = slen[i]; } } if (max_len == 0) { if (i_empty >= 0 && start < src) { if (xmlBufferAdd(buf, start, src - start) || xmlBufferAdd(buf, replace[i_empty], rlen[i_empty])) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); goto fail_buffer_add; } start = src; } src += xmlUTF8Size(src); } else { if ((start < src && xmlBufferAdd(buf, start, src - start)) || (rlen[i_match] && xmlBufferAdd(buf, replace[i_match], rlen[i_match]))) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); goto fail_buffer_add; } src += slen[i_match]; start = src; } } if (start < src && xmlBufferAdd(buf, start, src - start)) { xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); goto fail_buffer_add; } /* create result node set */ exsltStrReturnString(ctxt, xmlBufferContent(buf), xmlBufferLength(buf)); /* clean up */ fail_buffer_add: xmlBufferFree(buf); fail_buffer: fail_process_args: if (search_set != NULL) { for (i=0; i<n; ++i) xmlFree(search[i]); } if (replace_set != NULL) { for (i=0; i<n; ++i) { if (replace[i] != NULL) xmlFree(replace[i]); } } if (mem != NULL) xmlFree(mem); fail_malloc: done_empty_search: xmlFree(string); fail_string: if (search_set != NULL) xmlXPathFreeNodeSet(search_set); else xmlFree(search_str); fail_search: if (replace_set != NULL) xmlXPathFreeNodeSet(replace_set); else xmlFree(replace_str); fail_replace: return; }
bool MainWindow::OpenOSM(const QString &file_name) { scene_.clear(); FreeXMLDoc(); xmlParserCtxtPtr xml_parser_ctx_ptr = xmlNewParserCtxt(); if (0 == xml_parser_ctx_ptr) return false; // XML документ libxml2 xml_doc_ptr_ = xmlCtxtReadFile(xml_parser_ctx_ptr, file_name.toLocal8Bit().data(), 0, XML_PARSE_NOBLANKS); xmlFreeParserCtxt(xml_parser_ctx_ptr); xml_parser_ctx_ptr = 0; if (0 == xml_doc_ptr_) return false; xmlXPathContextPtr xpath_context_ptr = xmlXPathNewContext(xml_doc_ptr_); if (0 == xpath_context_ptr) return false; // Определеяем границы листа xmlXPathObjectPtr xpath_bounds_query = xmlXPathEvalExpression( BAD_CAST "//bounds", xpath_context_ptr); if ((0 == xpath_bounds_query) || (1 != xpath_bounds_query->nodesetval->nodeNr)) return false; xmlNodePtr bounds = xpath_bounds_query->nodesetval->nodeTab[0]; float minlat = QString::fromUtf8((char *)xmlGetProp(bounds, BAD_CAST "minlat")).toFloat(); float minlon = QString::fromUtf8((char *)xmlGetProp(bounds, BAD_CAST "minlon")).toFloat(); float maxlat = QString::fromUtf8((char *)xmlGetProp(bounds, BAD_CAST "maxlat")).toFloat(); float maxlon = QString::fromUtf8((char *)xmlGetProp(bounds, BAD_CAST "maxlon")).toFloat(); // Настраиваем область видимости ui->graphicsView->resetTransform(); ui->graphicsView->centerOn((maxlon - minlon) * 0.5, (maxlat - minlat) * 0.5); ui->graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter); qreal sx = 8000; qreal sy = 10000; ui->graphicsView->scale(sx, -sy); // Перебираем слои int layers_count = ui->treeWidget->topLevelItemCount(); for (int layer_index = 0; layer_index < layers_count; layer_index++){ QTreeWidgetItem *layer_item_ptr = ui->treeWidget->topLevelItem(layer_index); QString ways_count("0"); layer_item_ptr->setText(LAYERS_OBJECTS_COUNT_COLUMN, ways_count); QString way_query = layer_item_ptr->data(LAYERS_XPATH_COLUMN, 0).toString(); xmlXPathObjectPtr xpath_way_query = xmlXPathEvalExpression( BAD_CAST way_query.toUtf8().data(), xpath_context_ptr); if (0 == xpath_way_query) continue; xmlNodeSetPtr way_set = xpath_way_query->nodesetval; if ((0 == way_set) || (0 == way_set->nodeNr)) continue; QPen pen(Qt::darkGray); QBrush brush(Qt::lightGray); QList<QGraphicsItem*> layer; ways_count.setNum(way_set->nodeNr); layer_item_ptr->setText(LAYERS_OBJECTS_COUNT_COLUMN, ways_count); for (int i = 0; i < way_set->nodeNr; i++){ xmlNodePtr way = way_set->nodeTab[i]; if (0 == way) continue; // Создаем массив точек QPolygonF polygon; QString way_id = QString::fromUtf8((char *)xmlGetProp(way, BAD_CAST "id")); QString nd_query = QString("//way[@id='%1']/nd").arg(way_id); // Перебираем ссылки на точки xmlXPathObjectPtr xpath_nd_query = xmlXPathEvalExpression( BAD_CAST nd_query.toUtf8().data(), xpath_context_ptr); if ((0 == xpath_nd_query) || (0 == xpath_nd_query->nodesetval)) continue; for (int nd_index = 0; nd_index < xpath_nd_query->nodesetval->nodeNr; nd_index++){ QString ref = QString::fromUtf8((char *)xmlGetProp(xpath_nd_query->nodesetval->nodeTab[nd_index], BAD_CAST "ref")); // Ищем точку QString node_query = QString("//node[@id='%1']").arg(ref); xmlXPathObjectPtr xpath_node_query = xmlXPathEvalExpression( BAD_CAST node_query.toUtf8().data(), xpath_context_ptr); if ((0 == xpath_node_query) || (1 != xpath_node_query->nodesetval->nodeNr)) continue; xmlNodePtr node = xpath_node_query->nodesetval->nodeTab[0]; QString latitude = QString::fromUtf8((char *)xmlGetProp(node, BAD_CAST "lat")); QString longitude = QString::fromUtf8((char *)xmlGetProp(node, BAD_CAST "lon")); polygon.append(QPointF(longitude.toFloat(), latitude.toFloat())); xmlXPathFreeNodeSet(xpath_node_query->nodesetval); xmlFree(xpath_node_query); } // Создаем графический объект QGraphicsPolygonItem *polygon_item = new QGraphicsPolygonItem(polygon); polygon_item->setPen(pen); polygon_item->setBrush(brush); layer.append(polygon_item); xmlXPathFreeNodeSet(xpath_nd_query->nodesetval); xmlFree(xpath_nd_query); } QGraphicsItemGroup* layer_group = scene_.createItemGroup(layer); xmlXPathFreeNodeSet(way_set); xmlFree(xpath_way_query); } xmlXPathFreeContext(xpath_context_ptr); xpath_context_ptr = 0; return true; }
/** This extension function is designed to be used in a sanity test with an * XPath expression like this: * "//entry[ fd:unbalanced-braces(.//orth | .//tr | .//note | .//def | .//q) ]" * Before its use, a namespace prefix like "fd" has to be bound to * FREEDICT_EDITOR_NAMESPACE. */ static void freedict_xpath_extension_unbalanced_braces( xmlXPathParserContextPtr ctxt, const int nargs) { if(nargs != 1) { xmlXPathSetArityError(ctxt); return; } xmlNodeSetPtr ns = xmlXPathPopNodeSet(ctxt); if(xmlXPathCheckError(ctxt) || !ns) { xmlXPathFreeNodeSet(ns); return; } // function that does the actual parsing // returns TRUE if a brace of the string in c does not have // a corresponding brace gboolean contains_unbalanced_braces(xmlChar *c) { if(!c) return FALSE; char stack[100]; int stackend = sizeof(stack); // returns FALSE on stack full gboolean cub_push(const char b) { if(!stackend) { g_printerr(G_STRLOC ": Too many open braces"); return FALSE; } stack[--stackend] = b; return TRUE; } gchar cub_pop() { // stack is empty if(stackend>=sizeof(stack)) return 'E'; return stack[stackend++]; } do { switch(*c) { case '(': if(!cub_push('(')) return TRUE; break; case '[': if(!cub_push('[')) return TRUE; break; case '{': if(!cub_push('{')) return TRUE; break; case ')': if(cub_pop()!='(') return TRUE;break; case ']': if(cub_pop()!='[') return TRUE;break; case '}': if(cub_pop()!='{') return TRUE;break; // all other characters are skipped } c++; } while(*c); // braces left open? if(cub_pop()!='E') return TRUE; // this string is well formed in regard of braces return FALSE; } int result = FALSE; int i; for(i=0; i < xmlXPathNodeSetGetLength(ns); i++) { xmlNodePtr n = xmlXPathNodeSetItem(ns, i); xmlChar* c = xmlNodeGetContent(n); if(!c) continue; result = contains_unbalanced_braces(c); xmlFree(c); if(result) break; } if(ns) xmlXPathFreeNodeSet(ns); xmlXPathReturnBoolean(ctxt, result); }
/** * exsltStrReplaceFunction: * @ctxt: an XPath parser context * @nargs: the number of arguments * * Takes a string, and two node sets and returns the string with all strings in * the first node set replaced by all strings in the second node set. */ static void exsltStrReplaceFunction (xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *str = NULL, *searchStr = NULL, *replaceStr = NULL; xmlNodeSetPtr replaceSet = NULL, searchSet = NULL; xmlChar *ret = NULL, *retSwap = NULL; int i; if (nargs != 3) { xmlXPathSetArityError(ctxt); return; } /* pull out replace argument */ if (!xmlXPathStackIsNodeSet(ctxt)) { replaceStr = xmlXPathPopString(ctxt); } else { replaceSet = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { xmlXPathSetTypeError(ctxt); goto fail; } } /* behavior driven by search argument from here on */ if (!xmlXPathStackIsNodeSet(ctxt)) { searchStr = xmlXPathPopString(ctxt); str = xmlXPathPopString(ctxt); if (replaceStr == NULL) { xmlXPathSetTypeError(ctxt); goto fail; } ret = exsltStrReplaceInternal(str, searchStr, replaceStr); } else { searchSet = xmlXPathPopNodeSet(ctxt); if (searchSet == NULL || xmlXPathCheckError(ctxt)) { xmlXPathSetTypeError(ctxt); goto fail; } str = xmlXPathPopString(ctxt); ret = xmlStrdup(str); for (i = 0; i < searchSet->nodeNr; i++) { searchStr = xmlXPathCastNodeToString(searchSet->nodeTab[i]); if (replaceSet != NULL) { replaceStr = NULL; if (i < replaceSet->nodeNr) { replaceStr = xmlXPathCastNodeToString(replaceSet->nodeTab[i]); } retSwap = exsltStrReplaceInternal(ret, searchStr, replaceStr); if (replaceStr != NULL) { xmlFree(replaceStr); replaceStr = NULL; } } else { retSwap = exsltStrReplaceInternal(ret, searchStr, replaceStr); } xmlFree(ret); if (searchStr != NULL) { xmlFree(searchStr); searchStr = NULL; } ret = retSwap; } if (replaceSet != NULL) xmlXPathFreeNodeSet(replaceSet); if (searchSet != NULL) xmlXPathFreeNodeSet(searchSet); } xmlXPathReturnString(ctxt, ret); fail: if (replaceStr != NULL) xmlFree(replaceStr); if (searchStr != NULL) xmlFree(searchStr); if (str != NULL) xmlFree(str); }
static void exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlChar *str = NULL; xmlNodeSetPtr nodeset = NULL; xsltTransformContextPtr tctxt; xmlXPathCompExprPtr comp = NULL; xmlXPathObjectPtr ret = NULL; xmlDocPtr oldDoc, container = NULL; xmlNodePtr oldNode; int oldContextSize; int oldProximityPosition; int i, j; if (nargs != 2) { xmlXPathSetArityError(ctxt); return; } str = xmlXPathPopString(ctxt); if (xmlXPathCheckError(ctxt)) { xmlXPathSetTypeError(ctxt); return; } nodeset = xmlXPathPopNodeSet(ctxt); if (xmlXPathCheckError(ctxt)) { xmlXPathSetTypeError(ctxt); return; } if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) { if (nodeset != NULL) xmlXPathFreeNodeSet(nodeset); if (str != NULL) xmlFree(str); valuePush(ctxt, xmlXPathNewNodeSet(NULL)); return; } ret = xmlXPathNewNodeSet(NULL); if (ret == NULL) { xsltGenericError(xsltGenericErrorContext, "exsltDynMapFunction: ret == NULL\n"); goto cleanup; } oldDoc = ctxt->context->doc; oldNode = ctxt->context->node; oldContextSize = ctxt->context->contextSize; oldProximityPosition = ctxt->context->proximityPosition; tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "dyn:map : internal error tctxt == NULL\n"); goto cleanup; } container = xsltCreateRVT(tctxt); if (container == NULL) { xsltTransformError(tctxt, NULL, NULL, "dyn:map : internal error container == NULL\n"); goto cleanup; } xsltRegisterLocalRVT(tctxt, container); if (nodeset && nodeset->nodeNr > 0) { xmlXPathNodeSetSort(nodeset); ctxt->context->contextSize = nodeset->nodeNr; ctxt->context->proximityPosition = 0; for (i = 0; i < nodeset->nodeNr; i++) { xmlXPathObjectPtr subResult = NULL; ctxt->context->proximityPosition++; ctxt->context->node = nodeset->nodeTab[i]; ctxt->context->doc = nodeset->nodeTab[i]->doc; subResult = xmlXPathCompiledEval(comp, ctxt->context); if (subResult != NULL) { switch (subResult->type) { case XPATH_NODESET: if (subResult->nodesetval != NULL) for (j = 0; j < subResult->nodesetval->nodeNr; j++) xmlXPathNodeSetAdd(ret->nodesetval, subResult->nodesetval-> nodeTab[j]); break; case XPATH_BOOLEAN: if (container != NULL) { xmlNodePtr cur = xmlNewChild((xmlNodePtr) container, NULL, BAD_CAST "boolean", BAD_CAST (subResult-> boolval ? "true" : "")); if (cur != NULL) { cur->ns = xmlNewNs(cur, BAD_CAST "http://exslt.org/common", BAD_CAST "exsl"); xmlXPathNodeSetAddUnique(ret->nodesetval, cur); } xsltExtensionInstructionResultRegister(tctxt, ret); } break; case XPATH_NUMBER: if (container != NULL) { xmlChar *val = xmlXPathCastNumberToString(subResult-> floatval); xmlNodePtr cur = xmlNewChild((xmlNodePtr) container, NULL, BAD_CAST "number", val); if (val != NULL) xmlFree(val); if (cur != NULL) { cur->ns = xmlNewNs(cur, BAD_CAST "http://exslt.org/common", BAD_CAST "exsl"); xmlXPathNodeSetAddUnique(ret->nodesetval, cur); } xsltExtensionInstructionResultRegister(tctxt, ret); } break; case XPATH_STRING: if (container != NULL) { xmlNodePtr cur = xmlNewChild((xmlNodePtr) container, NULL, BAD_CAST "string", subResult->stringval); if (cur != NULL) { cur->ns = xmlNewNs(cur, BAD_CAST "http://exslt.org/common", BAD_CAST "exsl"); xmlXPathNodeSetAddUnique(ret->nodesetval, cur); } xsltExtensionInstructionResultRegister(tctxt, ret); } break; default: break; } xmlXPathFreeObject(subResult); } } } ctxt->context->doc = oldDoc; ctxt->context->node = oldNode; ctxt->context->contextSize = oldContextSize; ctxt->context->proximityPosition = oldProximityPosition; cleanup: if (comp != NULL) xmlXPathFreeCompExpr(comp); if (nodeset != NULL) xmlXPathFreeNodeSet(nodeset); if (str != NULL) xmlFree(str); valuePush(ctxt, ret); return; }