Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

mlview-parsing-utils.c

Go to the documentation of this file.
00001 /*
00002  *This file is part of MlView
00003  *
00004  *MlView is free software; you can redistribute it and/or modify it under the terms of 
00005  *the GNU General Public License as published by the Free Software Foundation; either version 2, 
00006  *or (at your option) any later version.
00007  *
00008  *MlView is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
00009  *without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00010  *See the GNU General Public License for more details.
00011  *
00012  *You should have received a copy of the GNU General Public License along with MlView; 
00013  *see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00014  *
00015  *
00016  *Copyright 2001-2002 Dodji Seketeli.
00017  */
00018 
00019 
00020 /*=======================================================
00021   This file contains various helper functions using during xml docs
00022   parsing.
00023  *========================================================*/
00024 
00025 #include <string.h>
00026 #include <libxml/parser.h>
00027 #include <libxml/catalog.h>
00028 #include <libxml/parserInternals.h>
00029 #include <libxml/xmlmemory.h>
00030 #include <libxml/SAX.h>
00031 #include <libxml/xmlerror.h>
00032 #include <libxml/uri.h>
00033 #include <libxml/hash.h>
00034 
00035 #include "utils.h"
00036 
00037 #include "mlview-parsing-utils.h"
00038 #include "mlview-global-settings.h"
00039 #include "mlview-file-descriptor.h"
00040 
00041 static MlViewExternalSubsetDefinition * p_external_subset_def=NULL ;
00042 static gboolean p_store_external_subset_def = FALSE ;
00043 static const gint MAX_NUMBER_OF_ELEMENT_NAMES_IN_CHOICE_LIST = 256 ;
00044 extern int xmlDoValidityCheckingDefaultValue ;
00045 
00046 #ifdef MLVIEW_DATA_DIR
00047 static const gchar * gv_mlview_data_dir = MLVIEW_DATA_DIR ;
00048 #else
00049 static const gchar * gv_mlview_data_dir = NULL
00050 #endif
00051 
00052 #ifdef MLVIEW_XML_CATALOG_DIR_NAME
00053 static const gchar * gv_mlview_xml_catalog_dir_name = MLVIEW_XML_CATALOG_DIR_NAME ;
00054 #else
00055 static const gchar * gv_mlview_xml_catalog_dir_name = NULL ;
00056 #endif
00057 
00058 typedef struct _MlViewCustomParserContext MlViewCustomParserContext ;
00059 
00064 struct _MlViewCustomParserContext {
00065         xmlParserCtxt initial_context ;
00066         MlViewAppContext * mlview_app_context ;
00067 } ;
00068 
00069 static MlViewCustomParserContext * 
00070 mlview_custom_parser_context_new (xmlParserCtxt *a_xml_parser_ctxt,
00071                                                                      MlViewAppContext * a_mlview_app_context) ;
00072 
00073 static void 
00074 mlview_custom_parser_context_destroy (MlViewCustomParserContext * a_context) ;
00075 
00076 
00077 /*helper function declarations*/
00078 static MlViewExternalSubsetDefinition * 
00079 mlview_external_subset_definition_clone (MlViewExternalSubsetDefinition * a_ext_subs_def) ;
00080 
00081 static xmlParserInput * 
00082 mlview_custom_external_entity_loader (const char *URL, const char * ID,
00083                                       xmlParserCtxt *a_context) ;
00084 
00085 static void 
00086 mlview_custom_external_subset_sax_handler (void *a_ctx, 
00087                                            const xmlChar *a_name,
00088                                            const xmlChar *a_external_id, 
00089                                            const xmlChar *a_system_id) ;
00090 
00091 
00092 static xmlParserInput * 
00093 mlview_custom_sax_resolve_entity (void *a_ctx, const xmlChar *a_public_id, 
00094                                   const xmlChar * a_system_id) ;
00095 
00096 static int 
00097 load_xml_document_from_local_file (gchar * a_xml_file_name, 
00098                                    xmlParserCtxtPtr *a_parser_context, 
00099                                    gboolean a_store_external_subset_info,
00100                                    MlViewAppContext * a_app_context) ;
00101 
00102 static xmlDtdPtr custom_xmlSAXParseDTD (MlViewAppContext *a_app_context, xmlSAXHandlerPtr sax,
00103                                         const xmlChar *ExternalID, const xmlChar *SystemID)  ;
00104 
00105 
00106 static gboolean 
00107 mlview_parsing_utils_ask_user_for_DTD_change_and_validation (MlViewAppContext *a_app_context,
00108                                                              const gchar * a_external_id,
00109                                                              const gchar * a_system_id, 
00110                                                              MlViewExternalSubsetDefinition ** a_external_subset_def) ;
00111 
00112 static gboolean 
00113 mlview_can_resolve_external_entity (MlViewAppContext * a_app_context, 
00114                                     const xmlChar *a_external_id, 
00115                                     const xmlChar *a_system_id) ;
00116 
00117 
00118 static void
00119 mlview_parsing_utils_scan_and_build_entities_list (void * a_hash_data,
00120                                                    void * a_output_list, 
00121                                                    void * a_entity_name) ;
00122 
00123 static void
00124 mlview_parsing_utils_scan_and_build_ids_list (void * a_hash_data,
00125                                               void * a_output_list,
00126                                               void * a_id_value) ;
00127 
00128 static void
00129 build_required_element_content (MlViewAppContext *a_app_context,
00130                                 xmlElementContent * a_content,
00131                                 xmlNode **a_node) ;
00132 
00133 static gint
00134 g_list_compare_string_elems (gchar *a_elem1, gchar *a_elem2) ;
00135 
00136 static gboolean
00137 is_an_ancestor_node (xmlNode *a_ancestor, xmlNode *a_cur_node) ;
00138 
00143 MlViewExternalSubsetDefinition * 
00144 mlview_external_subset_definition_new (const gchar *a_root_element_name,
00145                                        const gchar * a_external_id,
00146                                        const gchar * a_system_id)
00147 
00148 {
00149         MlViewExternalSubsetDefinition * result ;
00150 
00151         result = g_malloc0(sizeof(MlViewExternalSubsetDefinition)) ;
00152 
00153         if(a_external_id != NULL)
00154                 result->external_id = g_strdup(a_external_id) ;
00155 
00156         if(a_system_id != NULL)
00157                 result->system_id = g_strdup(a_system_id) ;
00158 
00159         if(a_root_element_name != NULL)
00160                 result->root_element_name = g_strdup(a_root_element_name) ;
00161 
00162         return result ;
00163 }
00164 
00165 
00169 static MlViewExternalSubsetDefinition * 
00170 mlview_external_subset_definition_clone (MlViewExternalSubsetDefinition * a_ext_subs_def)
00171 {
00172         g_return_val_if_fail(a_ext_subs_def != NULL, NULL) ;
00173         return mlview_external_subset_definition_new (a_ext_subs_def->root_element_name,
00174                                                       a_ext_subs_def->external_id,
00175                                                       a_ext_subs_def->system_id) ;
00176 }
00177 
00178 
00183 void 
00184 mlview_external_subset_definition_destroy (MlViewExternalSubsetDefinition * a_def)
00185 {
00186         g_return_if_fail (a_def != NULL) ;
00187         
00188         if (a_def->external_id != NULL ) {
00189                 g_free (a_def->external_id) ;
00190                 a_def->external_id = NULL ;
00191         }
00192 
00193         if (a_def->system_id != NULL) {
00194                 g_free (a_def->system_id)  ;
00195                 a_def->system_id = NULL ;
00196         }
00197 
00198         if (a_def->root_element_name != NULL) {
00199                 g_free (a_def->root_element_name) ;
00200                 a_def->root_element_name = NULL ;
00201         }
00202 
00203         g_free (a_def) ;
00204 }
00205 
00210 static 
00211 MlViewCustomParserContext * 
00212 mlview_custom_parser_context_new (xmlParserCtxt *a_xml_parser_ctxt,
00213                                   MlViewAppContext * a_mlview_app_context)
00214 {
00215         MlViewCustomParserContext * result=NULL ;
00216         g_return_val_if_fail (a_xml_parser_ctxt != NULL, NULL) ;
00217         
00218         result = g_malloc0 (sizeof (MlViewCustomParserContext)) ;
00219         g_assert (result != NULL) ;
00220         memmove (&result->initial_context, a_xml_parser_ctxt, sizeof (xmlParserCtxt)) ;
00221         result->mlview_app_context = a_mlview_app_context ;
00222         ((xmlParserCtxt*)result)->userData = result ;
00223         return result ;
00224 }
00225 
00226 
00230 static void
00231 mlview_custom_parser_context_destroy (MlViewCustomParserContext * a_context)
00232 {
00233         g_return_if_fail (a_context != NULL) ;
00234         g_free (a_context) ;
00235 }
00236 
00237 
00248 static int
00249 load_xml_document_from_local_file (gchar * a_xml_file_name, 
00250                                    xmlParserCtxt ** a_parser_context,
00251                                    gboolean a_store_external_subset_info,
00252                                    MlViewAppContext * a_app_context)
00253 {
00254         FILE * file_ptr ;
00255         int size = 1024, num_of_chars_read = 0, parse_status ;
00256         gchar file_buffer[size] ;
00257         MlViewCustomParserContext * custom_parser_context ;
00258         gchar * validation_is_on = NULL ;
00259         xmlDoValidityCheckingDefaultValue = 0 ;/*initialyze validation flag to "false" => no validation*/
00260 
00261         if (a_app_context)
00262                 validation_is_on = 
00263                         mlview_app_context_get_settings_value (a_app_context, MLVIEW_STG_K_IS_VALIDATION_ON) ;
00264 
00265         /*now, open the xml file...*/
00266         g_return_val_if_fail ( a_xml_file_name != NULL, MLVIEW_UTILS_ERR_FILE_NAME_NULL) ;
00267     
00268         file_ptr = fopen (a_xml_file_name, "r") ;
00269         g_return_val_if_fail ( file_ptr != NULL,
00270                                MLVIEW_UTILS_ERR_BAD_FILE ) ;
00271         num_of_chars_read = fread ( file_buffer, 1 ,4,file_ptr) ;
00272         g_return_val_if_fail ( num_of_chars_read > 0,MLVIEW_UTILS_ERR_EMPTY_FILE ) ;
00273 
00274         /*
00275          *Force the parser to ignore ignorable white spaces so that
00276          *indentation can be made properly at save time.
00277          */
00278         xmlKeepBlanksDefault (0) ;
00279 
00280         (*a_parser_context) = 
00281                 xmlCreatePushParserCtxt (NULL,NULL,
00282                                          file_buffer,num_of_chars_read,a_xml_file_name) ;
00283 
00284         /*let's create a custom parser context that inherits the native
00285          *libxml's xmlParserCtxt. That custom parser context embedds the MlViewAppContext.
00286          *that's usefull for our custom SAX handlers ... that way, the custom SAX handlers
00287          *we've written can take full advantage of the capabilities of the MlViewAppContext object.
00288          */
00289         custom_parser_context = mlview_custom_parser_context_new (*a_parser_context,
00290                                                                   a_app_context) ;
00291         g_return_val_if_fail (custom_parser_context != NULL, 
00292                               MLVIEW_UTILS_ERR) ;
00293 
00294 
00295         if (a_store_external_subset_info == TRUE) {/*overload the externalSubset sax handler with our custom one
00296                                                     *that stores the info about the external subset declared in the xml doc
00297                                                     *so that we can do post parsing validation.
00298                                                     */
00299                 /*overload the externalSubset sax handler*/
00300                 ((xmlParserCtxt*)custom_parser_context)->sax->externalSubset = mlview_custom_external_subset_sax_handler ;
00301                 ((xmlParserCtxt*)custom_parser_context)->sax->resolveEntity = mlview_custom_sax_resolve_entity ;
00302                 
00303                 /*tell the custom sax handler to save the external subset definition ... or not*/
00304                 p_store_external_subset_def = a_store_external_subset_info ;
00305         }
00306         
00307         /*override the error messaging stream of libxml*/
00308         xmlSetGenericErrorFunc(a_app_context, (xmlGenericErrorFunc) mlview_app_context_bufferize_error) ;
00309 
00310         while ( (num_of_chars_read = fread (file_buffer,1,size,file_ptr)) >0 ) {
00311                 parse_status = xmlParseChunk ((xmlParserCtxt*) custom_parser_context,
00312                                               file_buffer,num_of_chars_read, 0) ;
00313 
00314                 if (parse_status != XML_ERR_OK)
00315                         break ;
00316         }
00317 
00318         /*call the xmlParseChunk once more 2 consume all the data stored in the parser internal cache ...*/
00319         if (parse_status == XML_ERR_OK) {
00320                 parse_status = 
00321                         xmlParseChunk ((xmlParserCtxt*) custom_parser_context,
00322                                        file_buffer,num_of_chars_read,1) ;
00323         }
00324 
00325         /*restore the error display stream of libxml*/
00326         xmlSetGenericErrorFunc(NULL, NULL) ;
00327 
00328         if ( a_app_context  &&  ! mlview_app_context_error_buffer_is_empty (a_app_context))
00329                 mlview_app_context_display_buffered_error (a_app_context) ;
00330         else
00331                 mlview_app_context_set_error_dialog_title (a_app_context, NULL) ;
00332         
00333 
00334         memcpy (*a_parser_context, custom_parser_context, sizeof (xmlParserCtxt)) ;
00335         mlview_custom_parser_context_destroy (custom_parser_context) ;
00336         custom_parser_context = NULL ;
00337 
00338         return (parse_status == XML_ERR_OK) ? 0 : parse_status ;
00339 }
00340 
00341 
00347 static xmlParserInput *
00348 mlview_custom_external_entity_loader (const char *URL, const char * ID,
00349                                       xmlParserCtxt *a_context )
00350 {
00351         xmlParserInput * result = NULL ;
00352         xmlChar *resource = NULL ;
00353         gchar * xml_catalog_file = NULL ;
00354         xmlCatalog * xml_catalog = NULL ;
00355         gboolean can_resolve = FALSE ;
00356 
00357         can_resolve = 
00358                 mlview_can_resolve_external_entity (((MlViewCustomParserContext*)a_context)->mlview_app_context, ID, URL) ;
00359         
00360         if (can_resolve == FALSE)
00361                 return NULL ;
00362 
00363         if (gv_mlview_data_dir && gv_mlview_xml_catalog_dir_name) {
00364                 xml_catalog_file = g_strconcat (gv_mlview_data_dir, "/", 
00365                                                gv_mlview_xml_catalog_dir_name, "/",                                      
00366                                                "catalog.xml",
00367                                                NULL) ;
00368         }
00369 
00370         if (a_context 
00371              &&((MlViewCustomParserContext*)a_context)->mlview_app_context)
00372                 xml_catalog = 
00373                         mlview_app_context_get_xml_catalog (((MlViewCustomParserContext*)a_context)->mlview_app_context) ;
00374         
00375         if (xml_catalog == NULL) {
00376                 xml_catalog = xmlLoadACatalog (xml_catalog_file) ;
00377                 mlview_app_context_set_xml_catalog (((MlViewCustomParserContext*)a_context)->mlview_app_context,
00378                                                     xml_catalog) ;
00379         }
00380 
00381         if (xml_catalog_file) {
00382                 g_free (xml_catalog_file) ;
00383                 xml_catalog_file = NULL ;
00384         }
00385 
00386         if (xml_catalog == NULL) {
00387                 mlview_app_context_error (((MlViewCustomParserContext*)a_context)->mlview_app_context,
00388                                           _("Could not load mlview xml catalog")) ;
00389                 return NULL ;
00390         }
00391 
00392         if (ID != NULL  ||  URL != NULL) {
00393                 resource = 
00394                         xmlACatalogResolve (xml_catalog, ID, URL) ;
00395         }
00396 
00397         if (resource == NULL) {
00398                 MlViewFileDescriptor * file_desc = NULL ;
00399                 gboolean is_readable = FALSE ;
00400 
00401                 file_desc = mlview_file_descriptor_new (URL) ;
00402                 if (!mlview_file_descriptor_is_readable (file_desc, &is_readable) && is_readable == TRUE)
00403                         result = xmlNewInputFromFile (a_context, mlview_file_descriptor_get_file_path (file_desc)) ;
00404                 else
00405                         result = NULL ;
00406                 if (file_desc)
00407                         mlview_file_descriptor_destroy (file_desc) ;
00408         }else {
00409                 result = xmlNewInputFromFile (a_context, resource) ;
00410         }
00411 
00412         if (resource) {
00413                 xmlFree (resource) ;
00414         }
00415 
00416         return result ;
00417 }
00418 
00419 
00423 static xmlParserInput *
00424 mlview_custom_sax_resolve_entity (void *a_ctx, const xmlChar *a_public_id, 
00425                                   const xmlChar * a_system_id)
00426 {
00427         xmlParserCtxt * parser_context = (xmlParserCtxt *) a_ctx ;
00428         xmlParserInput * result = NULL ;
00429         xmlChar *URI = NULL ;
00430         const gchar * base = NULL ;
00431 
00432         if (parser_context == NULL) {/*build a parser input cause we need it to
00433                                       *build a parser input.
00434                                       */
00435                 parser_context = xmlNewParserCtxt() ;
00436         }
00437 
00438         if (parser_context  && (parser_context->input != NULL))
00439                 base = (const char *) parser_context->input->filename ;
00440         if (base == NULL && parser_context)
00441                 base = parser_context->directory ;
00442 
00443         URI = xmlBuildURI (a_system_id, NULL) ;
00444         result = 
00445                 mlview_custom_external_entity_loader ( (const char *)URI,
00446                                                        (const char *)a_public_id,
00447                                                        parser_context) ;
00448         if (URI != NULL)
00449                 xmlFree (URI) ;
00450         
00451         return result ;
00452 }
00453 
00454 
00462 static gboolean
00463 mlview_can_resolve_external_entity (MlViewAppContext * a_app_context,
00464                                     const xmlChar *a_external_id, 
00465                                     const xmlChar *a_system_id)
00466 {
00467         xmlCatalog * xml_catalog = NULL ;
00468         gchar * xml_catalog_file = NULL, *resource = NULL ;
00469         MlViewFileDescriptor * file_desc = NULL ;
00470         gboolean result = FALSE ;
00471 
00472         g_return_val_if_fail (a_app_context != NULL, FALSE) ;
00473         g_return_val_if_fail (a_app_context != NULL, FALSE) ;
00474         g_return_val_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context), FALSE) ;
00475 
00476         if (gv_mlview_data_dir && gv_mlview_xml_catalog_dir_name) {
00477                 xml_catalog_file = g_strconcat (gv_mlview_data_dir, "/",
00478                                                 gv_mlview_xml_catalog_dir_name, "/",
00479                                                 "catalog.xml",
00480                                                 NULL) ;
00481         }
00482 
00483         xml_catalog = mlview_app_context_get_xml_catalog (a_app_context) ;
00484         
00485         if (xml_catalog == NULL) {
00486                 xml_catalog = xmlLoadACatalog (xml_catalog_file) ;
00487                 mlview_app_context_set_xml_catalog (a_app_context, xml_catalog) ;
00488         }
00489 
00490         if (xml_catalog_file) {
00491                 g_free (xml_catalog_file) ;
00492                 xml_catalog_file = NULL ;
00493         }
00494 
00495         if (xml_catalog  == NULL) {
00496                 return FALSE ;
00497         }
00498 
00499         resource = xmlACatalogResolve (xml_catalog, a_external_id, 
00500                                        a_system_id) ;
00501         if (resource) {
00502                 xmlFree (resource) ;
00503                 return TRUE ;
00504         }
00505 
00506         /*the entity is not referenced by the xml catalog.
00507          *test if it is present on the local file system.
00508          */
00509         file_desc = mlview_file_descriptor_new (a_system_id) ;
00510 
00511         if (file_desc) {
00512                 gboolean is_readable = FALSE;
00513                 if (!mlview_file_descriptor_is_readable (file_desc, &is_readable) && is_readable == TRUE) {
00514                         result = TRUE ;
00515                 }
00516                 mlview_file_descriptor_destroy (file_desc) ;
00517                 file_desc = NULL ;
00518         }
00519 
00520         return result ;
00521 }
00522 
00536 static void
00537 mlview_custom_external_subset_sax_handler (void *a_ctx, const xmlChar *a_name,
00538                                            const xmlChar *a_external_id,
00539                                            const xmlChar *a_system_id)
00540 {
00541         MlViewCustomParserContext * custom_parser_context =
00542                 (MlViewCustomParserContext*)a_ctx ;
00543         gchar * validation_is_on = NULL ;
00544 
00545 
00546         if (custom_parser_context
00547             && custom_parser_context->mlview_app_context) {
00548                 validation_is_on = 
00549                         mlview_app_context_get_settings_value (custom_parser_context->mlview_app_context, 
00550                                                                MLVIEW_STG_K_IS_VALIDATION_ON) ;
00551         }
00552 
00553         if (validation_is_on 
00554             && (strcmp (validation_is_on, MLVIEW_STG_V_YES) == 0)
00555             && (xmlParserCtxt*)custom_parser_context)
00556                 ((xmlParserCtxt*)custom_parser_context)->validate = 1 ;
00557         else
00558                 ((xmlParserCtxt*)custom_parser_context)->validate = 0 ;
00559 
00560         /*
00561          *If validation is on, ask the user if she wants to choose another DTD but
00562          *the one referenced by the document in the doctype.
00563          */
00564         if (((xmlParserCtxt*)custom_parser_context)->validate == 1
00565             && (custom_parser_context->mlview_app_context != NULL)) {
00566                 MlViewExternalSubsetDefinition * external_subset_def = NULL ;
00567                gboolean validate = 
00568                        mlview_parsing_utils_ask_user_for_DTD_change_and_validation (custom_parser_context->mlview_app_context,
00569                                                                                     a_external_id,
00570                                                                                     a_system_id,
00571                                                                                     &external_subset_def) ;
00572                if (validate == FALSE)
00573                        ((xmlParserCtxt*)custom_parser_context)->validate = 0 ;
00574 
00575                if (validate && external_subset_def) {
00576                        a_external_id = external_subset_def->external_id ;
00577                        a_system_id = external_subset_def->system_id ;
00578                 }
00579         }
00580 
00581         if (((xmlParserCtxt*)custom_parser_context)->validate == 1) {
00582                 externalSubset(a_ctx, a_name, a_external_id, a_system_id) ;
00583                 if (((xmlParserCtxt*)a_ctx)->myDoc
00584                     && ((xmlParserCtxt*)a_ctx)->myDoc->extSubset == NULL) {
00585                         mlview_app_context_warning (custom_parser_context->mlview_app_context,
00586                                                     _("The external DTD subset was not found. I couldn't validate the document :(\n."));
00587                 }
00588         }
00589 
00590         /*
00591          *We will not do validation during the document parsing.
00592          *We will only do post parsing validation (if validation is required).
00593          */
00594         ((xmlParserCtxt*)custom_parser_context)->validate = 0 ;
00595 }
00596 
00597 
00598 static xmlDtdPtr
00599 custom_xmlSAXParseDTD (MlViewAppContext *a_app_context, xmlSAXHandlerPtr sax, 
00600                        const xmlChar *ExternalID, const xmlChar *SystemID)
00601 {
00602         xmlDtdPtr ret = NULL;
00603         xmlParserCtxtPtr ctxt;
00604         xmlParserInputPtr input = NULL;
00605         xmlCharEncoding enc;
00606         MlViewCustomParserContext * custom_parser_context = NULL ;
00607 
00608         if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
00609 
00610         ctxt = xmlNewParserCtxt();
00611         if (ctxt == NULL) {
00612                 return(NULL);
00613         }
00614         
00615         /*
00616          * Set-up the SAX context
00617          */
00618         if (sax != NULL) { 
00619                 if (ctxt->sax != NULL)
00620                         xmlFree(ctxt->sax);
00621                 ctxt->sax = sax ;
00622         }
00623 
00624         custom_parser_context = mlview_custom_parser_context_new (ctxt, a_app_context) ;
00625         
00626         /*
00627          * Ask the Entity resolver to load the damn thing
00628          */
00629 
00630         if ((custom_parser_context->initial_context.sax != NULL) && (custom_parser_context->initial_context.sax->resolveEntity != NULL))
00631                 input = custom_parser_context->initial_context.sax->resolveEntity(custom_parser_context->initial_context.userData, ExternalID, SystemID);
00632         if (input == NULL) {
00633                 if (sax != NULL) custom_parser_context->initial_context.sax = NULL;
00634                 mlview_custom_parser_context_destroy (custom_parser_context) ;
00635                 xmlFreeParserCtxt(ctxt);
00636                 return(NULL);
00637         }
00638 
00639         /*
00640          * plug some encoding conversion routines here.
00641          */
00642         xmlPushInput ((xmlParserCtxt*)&custom_parser_context->initial_context, input);
00643         enc = xmlDetectCharEncoding (custom_parser_context->initial_context.input->cur, 4);
00644         xmlSwitchEncoding ((xmlParserCtxt*) &custom_parser_context->initial_context, enc);
00645 
00646         if (input->filename == NULL)
00647                 input->filename = (char *) xmlStrdup(SystemID);
00648         input->line = 1;
00649         input->col = 1;
00650         input->base = custom_parser_context->initial_context.input->cur;
00651         input->cur = custom_parser_context->initial_context.input->cur;
00652         input->free = NULL;
00653 
00654         /*
00655          * let's parse that entity knowing it's an external subset.
00656          */
00657         custom_parser_context->initial_context.inSubset = 2;
00658         custom_parser_context->initial_context.myDoc = xmlNewDoc(BAD_CAST "1.0");
00659         custom_parser_context->initial_context.myDoc->extSubset = 
00660                 xmlNewDtd (custom_parser_context->initial_context.myDoc, BAD_CAST "none",
00661                            ExternalID, SystemID);
00662         xmlParseExternalSubset ((xmlParserCtxt*) &custom_parser_context->initial_context, ExternalID, SystemID);
00663 
00664         if (custom_parser_context->initial_context.myDoc != NULL) {
00665                 if (custom_parser_context->initial_context.wellFormed) {
00666                         ret = custom_parser_context->initial_context.myDoc->extSubset;
00667                         custom_parser_context->initial_context.myDoc->extSubset = NULL;
00668                 } else {
00669                         ret = NULL;
00670                 }
00671                 xmlFreeDoc(custom_parser_context->initial_context.myDoc);
00672                 custom_parser_context->initial_context.myDoc = NULL;
00673         }
00674 
00675         if (sax != NULL) custom_parser_context->initial_context.sax = NULL;
00676         mlview_custom_parser_context_destroy (custom_parser_context) ; 
00677         custom_parser_context = NULL ;
00678         xmlFreeParserCtxt (ctxt) ;
00679         ctxt = NULL ;
00680 
00681         return(ret);
00682 }
00683 
00691 static gboolean
00692 mlview_parsing_utils_ask_user_for_DTD_change_and_validation (MlViewAppContext *a_app_context,
00693                                                              const gchar * a_external_id,
00694                                                              const gchar * a_system_id,
00695                                                              MlViewExternalSubsetDefinition ** a_external_subset_def)
00696 {
00697         GnomeDialog * dialog = NULL ;
00698         gint button ;
00699         gboolean result = TRUE, can_resolve_entity = FALSE ;
00700         GtkWidget * label = NULL ;
00701         gchar * label_str = NULL ;
00702         const gchar *public_id = NULL ;
00703         const gchar *system_id = NULL ;
00704 
00705         g_return_val_if_fail (a_app_context != NULL, TRUE) ;
00706         g_return_val_if_fail (a_external_subset_def != NULL, TRUE) ;
00707 
00708         public_id = (const gchar *) (a_external_id != NULL) ? a_external_id : "\"\"" ;
00709         system_id = (const gchar *) (a_system_id != NULL) ? a_system_id : "\"\"" ;
00710 
00711         *a_external_subset_def = NULL ; /*sanity initialization*/
00712 
00713         can_resolve_entity = mlview_can_resolve_external_entity (a_app_context,a_external_id, 
00714                                                                  a_system_id) ;
00715 
00716         if (can_resolve_entity)
00717                 dialog = GNOME_DIALOG (gnome_dialog_new (_("Dtd choice"),
00718                                                          _("Load that DTD"), 
00719                                                          _("Choose another DTD"),
00720                                                          _("Do not validate"),
00721                                                          NULL)) ;
00722         else
00723                 dialog = GNOME_DIALOG (gnome_dialog_new (_("Dtd choice"),
00724                                                          _("Choose another DTD"),
00725                                                          _("Do not validate"),
00726                                                          NULL)) ;
00727 
00728         gtk_window_set_wmclass (GTK_WINDOW (dialog), "validation-confirmation", "MlView") ;
00729         
00730         if ( can_resolve_entity == TRUE)
00731                 label_str = 
00732                         g_strconcat (_("The document refers a DTD with:.\n"),
00733                                      _("Public ID => "), public_id, "\n",
00734                                      _("System ID => "), system_id, "\n",
00735                                      _("Do you want to load and use that DTD or choose another one ?\n"),
00736                                      NULL) ;
00737         else
00738                 label_str = 
00739                         g_strconcat (_("The document refers a DTD with:.\n"),
00740                                      _("Public ID => "), public_id, "\n",
00741                                      _("System ID => "), system_id, "\n",
00742                                      _("I have not found that DTD. Do you want to choose another one ?\n"),
00743                                      NULL) ;
00744         label = 
00745                 gtk_label_new (label_str) ;
00746 
00747         if (label_str) {
00748                 g_free (label_str) ;
00749                 label_str = NULL ;
00750         }
00751         gnome_dialog_close_hides (dialog, FALSE) ;
00752         gnome_dialog_set_close (dialog, FALSE) ;
00753         gtk_box_pack_start (GTK_BOX(dialog->vbox),
00754                             label, TRUE, TRUE, 0) ;
00755 
00756         gtk_widget_show_all (GTK_WIDGET (dialog->vbox)) ;
00757         
00758         gtk_widget_realize (GTK_WIDGET (dialog)) ;
00759         mlview_app_context_set_window_icon (a_app_context, GTK_WIDGET (dialog)) ;
00760         button = gnome_dialog_run (dialog) ;
00761         
00762         if (can_resolve_entity == TRUE) {
00763                 switch(button){
00764                 case 0: 
00765                                 /*user clicked the "Use that DTD" button*/                        
00766                         *a_external_subset_def = NULL ;
00767                         break ;
00768                 case 1: /*user clicked the "Choose another DTD" button*/
00769                         *a_external_subset_def = 
00770                                 mlview_parsing_utils_let_user_choose_a_dtd (a_app_context, _("Choose a DTD")) ;
00771                         result = (*a_external_subset_def == NULL)? FALSE : TRUE ;
00772                         break ;
00773                 case 2: /*user clicked the "Do not validate" button*/
00774                         result = FALSE ;/*do not validate*/
00775                         break ;
00776                 case -1:/*user closed the window using Window manager=>like case 0*/
00777                 default :
00778                         break ;
00779                 }
00780         } else {
00781                 switch(button){
00782                 case 0: /*user clicked the "Choose another DTD" button*/
00783                         *a_external_subset_def = 
00784                                 mlview_parsing_utils_let_user_choose_a_dtd (a_app_context, _("Choose a DTD")) ;
00785                         result = (*a_external_subset_def == NULL)? FALSE : TRUE ;
00786                         break ;
00787                 case 1: /*user clicked the "Do not validate" button*/
00788                         result = FALSE ;/*do not validate*/
00789                         break ;
00790                 case -1:/*user closed the window using Window manager=>like case 0*/
00791                 default :
00792                         break ;
00793                 }
00794         }
00795 
00796         if (dialog) {
00797                 gnome_dialog_close (dialog) ;
00798                 dialog = NULL ;
00799         }
00800 
00801         return result ;
00802 }
00803 
00804 
00817 static void
00818 mlview_parsing_utils_scan_and_build_entities_list (void * a_hash_data,
00819                                                    void * a_output_list,
00820                                                    void * a_entity_name)
00821 {
00822 
00823         if (a_entity_name)
00824                 *((GList**)a_output_list) = 
00825                         (void*) g_list_append (*((GList**)a_output_list),
00826                                                a_entity_name) ;
00827 }
00828 
00829 
00830 static void
00831 mlview_parsing_utils_scan_and_build_ids_list (void * a_hash_data,
00832                                               void * a_output_list,
00833                                               void * a_id_value)
00834 {
00835 
00836         if (a_id_value)
00837                 *((GList**)a_output_list) = 
00838                         (void*) g_list_append (*((GList**)a_output_list),
00839                                                a_id_value) ;
00840 }
00841 
00842 static gboolean
00843 is_an_ancestor_node (xmlNode *a_ancestor, xmlNode *a_cur_node)
00844 {
00845         xmlNode * mobile_ptr = a_cur_node ;
00846 
00847         g_return_val_if_fail (a_cur_node != NULL, FALSE) ;
00848         g_return_val_if_fail (a_ancestor != NULL, FALSE) ;
00849 
00850         while (mobile_ptr) {
00851                 if (xmlStrEqual (mobile_ptr->name, 
00852                                  a_ancestor->name))
00853                         return TRUE ;
00854                 mobile_ptr = mobile_ptr->parent ;
00855         }
00856         return FALSE ;
00857 }
00858 
00870 static void
00871 build_required_element_content (MlViewAppContext *a_app_context,
00872                                 xmlElementContent * a_content,
00873                                 xmlNode **a_node)
00874 {
00875         xmlElementContent * current_element_content = a_content ;
00876         xmlNode * child_node = NULL , *dummy = NULL;
00877 
00878         g_return_if_fail (a_app_context != NULL) ;
00879         g_return_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context)) ;
00880         g_return_if_fail (a_node != NULL) ;
00881         g_return_if_fail ((*a_node) != NULL) ;
00882 
00883         if (!current_element_content)
00884                 return ;
00885 
00886         dummy = xmlNewNode (NULL, "<!dummy>") ;
00887         switch (current_element_content->type) {
00888 
00889         case XML_ELEMENT_CONTENT_OR: 
00890         /*this element decl is a <!ELEMENT current (child1 | child2)> type.
00891          *Note that childi may be an element or a SEQ or whatever.
00892          */
00893                 
00894                 switch (current_element_content->ocur) {
00895                 case XML_ELEMENT_CONTENT_ONCE:
00896                 case XML_ELEMENT_CONTENT_PLUS:
00897                 /*ex: <!ELEMENT current (child1 | child2)> or
00898                  * <!ELEMENT current (child1 | child2)+> decl type.
00899                  *Note that childi may be an element or a SEQ or whatever.
00900                  *=> let's check wether if we will insert child1 or child2
00901                  *(that will depend on child1 and child2 cardinality)
00902                  */
00903                         if (current_element_content->type == XML_ELEMENT_CONTENT_ELEMENT
00904                             && current_element_content->name) {
00905 
00906                                 child_node = 
00907                                         xmlNewChild ((*a_node),
00908                                                      NULL, 
00909                                                      current_element_content->name,
00910                                                      NULL) ;
00911 
00912                                 mlview_parsing_utils_build_required_children_tree (a_app_context,
00913                                                                                    &child_node) ;
00914                                 
00915                         } else if (current_element_content->c1 
00916                                    && ((current_element_content->c1->ocur == XML_ELEMENT_CONTENT_ONCE)
00917                                        || current_element_content->c1->ocur == XML_ELEMENT_CONTENT_PLUS)
00918                                 ) {
00919                                 /*ex: <!ELEMENT current (child1 | child2*)+> decl type or 
00920                                  *even <!ELEMENT current (child1 | child2+)+>
00921                                  *Note that childi may be an element or a SEQ or whatever.
00922                                  *=>we explore child1 and not child2. => we won't keep child2
00923                                  */
00924                                 if (current_element_content->c1->type == XML_ELEMENT_CONTENT_ELEMENT) {
00925                                         dummy->name = current_element_content->c1->name  ;
00926                                         if (is_an_ancestor_node (dummy, *a_node) == FALSE) {
00927                                                 build_required_element_content (a_app_context,
00928                                                                                 current_element_content->c1,
00929                                                                                 a_node) ;
00930                                         } else {
00931                                                 build_required_element_content (a_app_context,
00932                                                                                 current_element_content->c2,
00933                                                                                 a_node) ;
00934                                         }
00935                                 } else {
00936                                         build_required_element_content (a_app_context,
00937                                                                         current_element_content->c1,
00938                                                                         a_node) ;
00939                                 }
00940                         } else {
00941                                 /*ex: <!ELEMENT current (child1* | child2+)+> decl type
00942                                  *Note that childi may be an element or a SEQ or whatever.
00943                                  *=> we won't explore child1 => we won't keep it.
00944                                  */
00945                                 build_required_element_content (a_app_context,
00946                                                                 current_element_content->c2,
00947                                                                 a_node) ;
00948                         }
00949                         break ;
00950                 default :
00951                         break ;
00952                 }
00953                 break ;
00954 
00955         default:
00956                 switch (current_element_content->ocur) {
00957                 case XML_ELEMENT_CONTENT_ONCE:
00958                 case XML_ELEMENT_CONTENT_PLUS:
00959                         if (current_element_content->name ) {
00960                                 
00961                                 child_node = 
00962                                         xmlNewChild ((*a_node),
00963                                                      NULL, 
00964                                                      current_element_content->name,
00965                                                      NULL) ;
00966 
00967                                 mlview_parsing_utils_build_required_children_tree (a_app_context,
00968                                                                                    &child_node) ;
00969                         } else {
00970                                 build_required_element_content (a_app_context,
00971                                                                 current_element_content->c1,
00972                                                                 a_node) ;
00973 
00974                                 build_required_element_content (a_app_context,
00975                                                                 current_element_content->c2,
00976                                                                 a_node) ;
00977                         }
00978                         
00979                         break ;
00980                 default :
00981                         break ;
00982                         
00983                 }
00984                 break ;
00985         }
00986         if (dummy) {
00987                 dummy->name = NULL ;
00988                 xmlFreeNode (dummy) ;
00989                 dummy = NULL ;
00990         }
00991 }
00992 
00993 
00994 static gint
00995 g_list_compare_string_elems (gchar *a_str1, gchar *a_str2)
00996 {
00997         g_return_val_if_fail (a_str1 != NULL, -1) ;
00998         g_return_val_if_fail (a_str2 != NULL, 1) ;
00999 
01000         return strcmp (a_str1, a_str2) ;
01001 }
01002 
01003 /*****************************************************************************
01004  *Public methods
01005  *****************************************************************************/
01006 
01015 xmlDoc *
01016 mlview_parsing_utils_load_xml_file (gchar * a_file_name, MlViewAppContext *a_app_context)
01017 {
01018         xmlDoc *result=NULL ;
01019         xmlParserCtxtPtr parser_context=NULL ;
01020 
01021         g_return_val_if_fail(a_file_name != NULL, NULL) ;
01022 
01023         if ( strcmp(a_file_name, "")) {
01024                 gint load_res ;
01025                 /*
01026                  *fixme: remember to add support of error handling while loading the document.
01027                  */
01028                 load_res = load_xml_document_from_local_file (a_file_name, &parser_context,TRUE, a_app_context) ;
01029                 
01030                 if ( parser_context == NULL ) {
01031                         mlview_app_context_error (a_app_context, _("could not load xml document %s"), a_file_name) ;
01032                         return NULL;
01033                 }
01034                 if ( !load_res && parser_context ) {
01035                         parser_context->myDoc->name = (xmlChar *) g_strdup(a_file_name);
01036                         result = parser_context->myDoc ;
01037                 }
01038         }
01039 
01040         if (parser_context != NULL) {
01041                 xmlFreeParserCtxt (parser_context) ;
01042         }
01043         return result;
01044 }
01045 
01046 
01056 gint
01057 mlview_parsing_utils_save_xml_doc (xmlDoc * a_xml_doc, gchar * a_file_path, 
01058                                    MlViewAppContext * a_app_context)
01059 {
01060         g_return_val_if_fail (a_xml_doc != NULL, -1) ;
01061         g_return_val_if_fail (a_file_path != NULL, -1) ;
01062 
01063         return xmlSaveFormatFile (a_file_path, 
01064                                   a_xml_doc, 
01065                                   1) ;
01066 }
01067 
01068 
01076 xmlDtd * 
01077 mlview_parsing_utils_load_a_dtd (MlViewExternalSubsetDefinition * a_subset_def,
01078                                  MlViewAppContext * a_app_context)
01079 {
01080         xmlDtd * dtd = NULL ;
01081         xmlSAXHandler * sax_handler = NULL ;
01082 
01083         g_return_val_if_fail (a_subset_def != NULL, NULL) ;
01084 
01085         if ( a_subset_def->system_id ) {                
01086 
01087                 /*Replace this function by xmlSAXParseDTD. => that will allow overloading of the resolveEntity handler.
01088                  *
01089                  */
01090                 sax_handler = (xmlSAXHandler*)xmlMalloc (sizeof (xmlSAXHandler)) ;
01091                 g_assert (sax_handler != NULL) ;
01092                 initxmlDefaultSAXHandler(sax_handler, 0) ;
01093 
01094                 g_assert (sax_handler != NULL) ;
01095                 
01096                 /*override the libxml error printing routine*/
01097                 xmlSetGenericErrorFunc (a_app_context, 
01098                                         (xmlGenericErrorFunc) mlview_app_context_bufferize_error) ;
01099                 mlview_app_context_set_error_dialog_title (a_app_context, 
01100                                                            _("Some error(s) occured during the parsing of the dtd.\n\n")) ;
01101 
01102                 /*overload the entity resolver.*/
01103                 sax_handler->resolveEntity = mlview_custom_sax_resolve_entity ;
01104 
01105                 dtd = custom_xmlSAXParseDTD (a_app_context, sax_handler,
01106                                              a_subset_def->external_id, a_subset_def->system_id) ;
01107 
01108                 /*restore the libxml error printing routine
01109                  *FIXME: it would be better re-think the error overidding/restoring process.
01110                  */
01111                 xmlSetGenericErrorFunc (NULL, NULL) ;
01112 
01113                 if ( !mlview_app_context_error_buffer_is_empty (a_app_context) )
01114                         mlview_app_context_display_buffered_error (a_app_context) ;
01115                 else
01116                         mlview_app_context_set_error_dialog_title (a_app_context, NULL) ;
01117         }
01118 
01119         return dtd ;
01120 }
01121 
01122 
01130 gint
01131 mlview_parsing_utils_validate_dtd (xmlDoc * a_doc, xmlDtd * a_dtd, 
01132                                    MlViewAppContext * a_app_context) 
01133 {
01134         gint result=0 ;
01135         gint validity_status ;
01136         xmlValidCtxt validation_context ;
01137         
01138         g_return_val_if_fail (a_doc != NULL, -1) ;
01139         
01140         if (a_dtd == NULL)
01141                 return 2 ;
01142         
01143         validation_context.userData = a_app_context ;
01144         validation_context.error = 
01145                 (xmlValidityErrorFunc) mlview_app_context_bufferize_error ;
01146         validation_context.warning = 
01147                 (xmlValidityWarningFunc) mlview_app_context_bufferize_error ;
01148 
01149         xmlSetGenericErrorFunc (a_app_context, (xmlGenericErrorFunc)mlview_app_context_bufferize_error) ;
01150         mlview_app_context_set_error_dialog_title (a_app_context, _("Some error(s) occured during the validation of the document.\n\n")) ;
01151         validity_status = xmlValidateDtd (&validation_context, a_doc, a_dtd) ;  
01152         xmlSetGenericErrorFunc (a_app_context, (xmlGenericErrorFunc)mlview_app_context_bufferize_error) ;
01153 
01154         if (validity_status == 1) /*xmlValidate() returns 1 if doc is valid 
01155                                    *whereas we want to return 0 in that case ...*/
01156                 result = 0 ;
01157         else
01158                 result = 1 ;
01159         if ( !mlview_app_context_error_buffer_is_empty (a_app_context) )
01160                 mlview_app_context_display_buffered_error (a_app_context) ;
01161         else
01162                 mlview_app_context_set_error_dialog_title (a_app_context, NULL) ;
01163 
01164         return result ;
01165 }
01166 
01167 
01175 MlViewExternalSubsetDefinition *
01176 mlview_utils_get_a_copy_of_last_external_subset_def (void)
01177 {
01178         MlViewExternalSubsetDefinition * result ;
01179 
01180         if (p_external_subset_def == NULL)
01181                 return NULL ;
01182         result = mlview_external_subset_definition_clone (p_external_subset_def) ;
01183         mlview_external_subset_definition_destroy (p_external_subset_def) ;
01184         p_external_subset_def = NULL ;
01185 
01186         return result ;
01187 }
01188 
01189 
01190 /*
01191  *mlview_parsing_utils_let_user_choose_a_dtd:
01192  *
01193  *
01194  */
01195 MlViewExternalSubsetDefinition *
01196 mlview_parsing_utils_let_user_choose_a_dtd (MlViewAppContext * a_app_context,
01197                                             gchar *a_title)
01198 {
01199         MlViewFileSelection * filesel = NULL ;
01200         MlViewExternalSubsetDefinition *subset_def = NULL ;
01201 
01202         enum MLVIEW_SELECTED_BUTTON button_clicked ;
01203         gchar * dtd=NULL ;
01204 
01205         g_return_val_if_fail(a_app_context != NULL, NULL) ;
01206 
01207         filesel = mlview_app_context_get_file_selector (a_app_context, a_title) ;
01208         g_return_val_if_fail (filesel != NULL, NULL) ;
01209 
01210         gtk_widget_realize (GTK_WIDGET (filesel)) ;
01211         mlview_app_context_set_window_icon (a_app_context, GTK_WIDGET (filesel)) ;
01212         button_clicked = mlview_file_selection_run (filesel, TRUE) ;
01213 
01214         switch (button_clicked) {
01215         case OK_BUTTON :
01216                 dtd = gtk_file_selection_get_filename (GTK_FILE_SELECTION (filesel)) ;
01217                 if (dtd)
01218                         subset_def = mlview_external_subset_definition_new (NULL, NULL, dtd) ;
01219                 break ;
01220         case CANCEL_BUTTON :
01221         case WINDOW_CLOSED :
01222         default :
01223                 break ;
01224         }
01225 
01226         return subset_def ;
01227 }
01228 
01241 gint
01242 mlview_parsing_utils_build_element_name_completion_list (MlViewAppContext *a_app_context,
01243                                                          enum NODE_INSERTION_SCHEME a_insertion_scheme,
01244                                                          xmlNode *a_current_xml_node,
01245                                                          GList ** a_feasible_names_ptr)
01246 {
01247         const xmlChar * feasible_names [MAX_NUMBER_OF_ELEMENT_NAMES_IN_CHOICE_LIST] ;
01248         gint nb_of_names = 0 ;
01249         gchar * validation_is_on = NULL ;
01250 
01251         g_return_val_if_fail (a_current_xml_node != NULL, -2) ;
01252         g_return_val_if_fail (a_current_xml_node->type == XML_ELEMENT_NODE, -2) ;
01253         g_return_val_if_fail (feasible_names != NULL, -2) ;
01254         
01255         memset (feasible_names, 0, MAX_NUMBER_OF_ELEMENT_NAMES_IN_CHOICE_LIST * sizeof (xmlChar*)) ;
01256 
01257         if (a_app_context
01258             && mlview_app_context_settings_exist (a_app_context))
01259                 validation_is_on =
01260                         mlview_app_context_get_settings_value (a_app_context,
01261                                                                MLVIEW_STG_K_IS_VALIDATION_ON) ;
01262 
01263         if ( (validation_is_on == NULL)
01264             || (strcmp (validation_is_on, MLVIEW_STG_V_YES) != 0))
01265                 return -1 ; /*validation is not turned on !!!*/
01266 
01267         if ( (a_insertion_scheme == INSERT_BEFORE)
01268              && (a_current_xml_node->type == XML_DOCUMENT_NODE)) {
01269                 return 0 ;/*invocation of xmlValidGetValidElements in this case cores libxml2-2.4.16*/
01270         }
01271 
01272         if ((a_insertion_scheme == INSERT_BEFORE)
01273             && a_current_xml_node->parent
01274             &&  a_current_xml_node->parent->type == XML_DOCUMENT_NODE) {
01275                 /*in this case, invocation of xmlValidGetValidElements with a document that have NULL name cores.*/
01276                 return 0 ;
01277         }
01278 
01279         if ( (a_insertion_scheme == INSERT_AFTER) 
01280              &&(a_current_xml_node->type == XML_DOCUMENT_NODE)){
01281                 return 0 ; /*invocation of xmlValidGetValidElements in this case cores libxml2-2.4.16*/
01282         }
01283 
01284         switch (a_insertion_scheme) {
01285         case INSERT_BEFORE: /*user wants to insert a node just before the current selected node*/
01286                 nb_of_names = 
01287                         xmlValidGetValidElements (a_current_xml_node->prev,
01288                                                   a_current_xml_node, 
01289                                                   feasible_names, 
01290                                                   MAX_NUMBER_OF_ELEMENT_NAMES_IN_CHOICE_LIST) ;
01291                 break ;
01292         case INSERT_AFTER:
01293                 nb_of_names =
01294                         xmlValidGetValidElements (a_current_xml_node,
01295                                                   a_current_xml_node->next,
01296                                                   feasible_names,
01297                                                   MAX_NUMBER_OF_ELEMENT_NAMES_IN_CHOICE_LIST) ;
01298                 break ;
01299 
01300         case ADD_CHILD :/*append child*/
01301                 if (a_current_xml_node->children) {
01302                         nb_of_names =
01303                                 xmlValidGetValidElements (a_current_xml_node->last,
01304                                                           NULL,
01305                                                           feasible_names,
01306                                                           MAX_NUMBER_OF_ELEMENT_NAMES_IN_CHOICE_LIST) ;
01307 
01308                 } else {
01309                         nb_of_names =
01310                                 xmlValidGetValidElementsChildren (a_current_xml_node,
01311                                                                   feasible_names,
01312                                                                   MAX_NUMBER_OF_ELEMENT_NAMES_IN_CHOICE_LIST) ;
01313                 }
01314                 
01315                         break ;
01316                 default :
01317                         break ;
01318                 }/*end switch*/
01319 
01320         if (nb_of_names > 0) {/*found some names to propose to the user*/
01321                 int i ;
01322                 GList * list_ptr = NULL ;
01323                 GHashTable * names_index = 
01324                         g_hash_table_new (g_str_hash, g_str_equal) ;
01325 
01326                 for (list_ptr = *a_feasible_names_ptr ;
01327                      list_ptr ;
01328                      list_ptr = list_ptr->next) {
01329 
01330                         if (list_ptr->data)
01331                                 g_hash_table_insert (names_index, 
01332                                                      list_ptr->data, 
01333                                                      list_ptr->data) ;
01334                 }
01335 
01336                 for (i=0 ; i < nb_of_names ; i++) {
01337 
01338                         if ( ((xmlChar**)feasible_names)[i] 
01339                              && !g_hash_table_lookup (names_index, ((xmlChar**)feasible_names)[i] )) {
01340 
01341                                 (*a_feasible_names_ptr) =
01342                                         g_list_append (*a_feasible_names_ptr,
01343                                                        ((xmlChar**)feasible_names)[i]) ;
01344                         }
01345                 }
01346                 g_hash_table_destroy (names_index) ;
01347                 *a_feasible_names_ptr = 
01348                         g_list_sort (*a_feasible_names_ptr,
01349                                      (GCompareFunc) g_list_compare_string_elems) ;
01350         }
01351 
01352         return nb_of_names ;
01353 }
01354 
01364 gint
01365 mlview_parsing_utils_build_attribute_name_completion_list (MlViewAppContext *a_app_context,
01366                                                            xmlNode * a_current_xml_node,
01367                                                            GList**a_attr_names_compl_list,
01368                                                            gboolean a_required_attributes_only)
01369 {
01370         xmlElement * element_desc  = NULL ;
01371         gchar * validation_is_on = NULL ;
01372         gint result = 0 ;
01373 
01374         g_return_val_if_fail (a_app_context != NULL, -2) ;
01375         g_return_val_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context), -2) ;
01376         g_return_val_if_fail (a_current_xml_node != NULL, -2) ;
01377         g_return_val_if_fail (a_attr_names_compl_list != NULL, -2) ;
01378 
01379         *a_attr_names_compl_list = NULL ;
01380 
01381         if (a_app_context
01382             && mlview_app_context_settings_exist (a_app_context))
01383                 validation_is_on =
01384                         mlview_app_context_get_settings_value (a_app_context, 
01385                                                                MLVIEW_STG_K_IS_VALIDATION_ON) ;
01386 
01387         if (validation_is_on == NULL
01388             || (strcmp (validation_is_on, MLVIEW_STG_V_YES) != 0))
01389                 return -1 ; /*validation is not turned on !!!*/
01390 
01391         if (a_current_xml_node->doc->intSubset != NULL )
01392                 element_desc = 
01393                         xmlGetDtdElementDesc (a_current_xml_node->doc->intSubset, 
01394                                               a_current_xml_node->name) ;
01395 
01396         if ( element_desc == NULL && a_current_xml_node->doc->extSubset )
01397                 element_desc = 
01398                         xmlGetDtdElementDesc (a_current_xml_node->doc->extSubset,
01399                                               a_current_xml_node->name) ;
01400 
01401         if ( element_desc != NULL
01402              && element_desc->attributes != NULL ) { /*build the list of attribute names*/
01403                 gboolean add_attribute ;
01404                 xmlAttribute * curr_attr = element_desc->attributes ;;
01405                 
01406                 while ( curr_attr ) {
01407                         if (a_required_attributes_only == TRUE
01408                             && curr_attr->def != XML_ATTRIBUTE_REQUIRED)
01409                                 add_attribute = FALSE ;
01410                         else
01411                                 add_attribute = TRUE ;
01412 
01413                         if (add_attribute == TRUE) {
01414                                 *a_attr_names_compl_list =
01415                                         g_list_append (*a_attr_names_compl_list,
01416                                                        (gpointer)curr_attr->name) ;
01417                                 result++ ;
01418                         }
01419                         curr_attr = curr_attr->nexth ;
01420                 }
01421         }
01422         
01423         *a_attr_names_compl_list = 
01424                 g_list_sort (*a_attr_names_compl_list,
01425                               (GCompareFunc) g_list_compare_string_elems) ;
01426         return result ;
01427 }
01428 
01429 
01439 enum MLVIEW_PARSING_UTILS_STATUS
01440 mlview_parsing_utils_get_element_content_table (MlViewAppContext * a_app_context,
01441                                                 xmlElementContent *a_element_content,
01442                                                 GHashTable **a_element_content_table)
01443 {
01444           gchar * validation_is_on = NULL ;
01445           enum MLVIEW_PARSING_UTILS_STATUS result = NOK ;
01446 
01447           g_return_val_if_fail (a_app_context != NULL, BAD_PARAMETER) ;
01448           g_return_val_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context), BAD_PARAMETER) ;
01449           
01450           if (a_element_content == NULL)
01451                   return OK ;
01452 
01453           validation_is_on =
01454                   mlview_app_context_get_settings_value (a_app_context, 
01455                                                          MLVIEW_STG_K_IS_VALIDATION_ON) ;
01456           
01457           if (validation_is_on == NULL
01458               || (strcmp (validation_is_on, MLVIEW_STG_V_YES) != 0))
01459                   return -1 ; /*validation is not turned on !!!*/
01460 
01461           if (!*a_element_content_table)
01462                   *a_element_content_table = g_hash_table_new (g_str_hash, g_str_equal) ; 
01463 
01464           g_return_val_if_fail (*a_element_content_table != NULL, GENERIC_ASSERTION_ERROR) ;
01465 
01466           switch (a_element_content->type) {
01467           case XML_ELEMENT_CONTENT_PCDATA:
01468                   result = OK ;
01469                   break ;
01470           case XML_ELEMENT_CONTENT_ELEMENT:
01471                   if (a_element_content->name == NULL
01472                       || g_hash_table_lookup (*a_element_content_table, a_element_content->name))
01473                           break ;
01474 
01475                   g_hash_table_insert (*a_element_content_table, (gpointer)a_element_content->name, a_element_content) ;
01476 
01477                   result = OK ;
01478                   break ;
01479 
01480           case XML_ELEMENT_CONTENT_SEQ:
01481           case XML_ELEMENT_CONTENT_OR:
01482                   mlview_parsing_utils_get_element_content_table (a_app_context,
01483                                                                   a_element_content->c1,
01484                                                                   a_element_content_table) ;
01485 
01486                   mlview_parsing_utils_get_element_content_table (a_app_context,
01487                                                                   a_element_content->c2,
01488                                                                   a_element_content_table) ;
01489                   result = OK ;
01490                   break ;
01491 
01492           default:
01493                   result = NOK ;
01494                   break ;
01495 
01496           }
01497 
01498           return result ;
01499 }
01500 
01501 
01511 enum MLVIEW_PARSING_UTILS_STATUS
01512 mlview_parsing_utils_build_required_attributes_list (MlViewAppContext * a_app_context,
01513                                                      xmlNode *a_node) 
01514 {
01515         GList *attributes_list = NULL, *list_ptr = NULL ;
01516         gint nb_of_attributes = 0 ;
01517         gchar * validation_is_on = NULL ;
01518 
01519         enum MLVIEW_PARSING_UTILS_STATUS result = NOK ;
01520         
01521         g_return_val_if_fail (a_app_context != NULL, BAD_PARAMETER) ;
01522         g_return_val_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context), BAD_PARAMETER) ;
01523         g_return_val_if_fail (a_node != NULL, BAD_PARAMETER) ;
01524 
01525         if (mlview_app_context_settings_exist (a_app_context) == FALSE)
01526                 return APP_SETTINGS_NOT_AVAILABLE ;
01527 
01528         validation_is_on = mlview_app_context_get_settings_value (a_app_context, MLVIEW_STG_K_IS_VALIDATION_ON) ;
01529 
01530         if (!validation_is_on 
01531             || strcmp (validation_is_on, MLVIEW_STG_V_YES))
01532                 return VALIDATION_IS_OFF ;
01533 
01534         nb_of_attributes = 
01535                 mlview_parsing_utils_build_attribute_name_completion_list (a_app_context, a_node, 
01536                                                                            &attributes_list, TRUE) ;
01537         if (nb_of_attributes < 0)
01538                 return NOK ;
01539 
01540         else if (nb_of_attributes == 0)
01541                 return OK ;
01542 
01543         result = OK ;
01544 
01545         for (list_ptr = attributes_list ; list_ptr ; list_ptr = list_ptr->next) {
01546                 if (!list_ptr->data) 
01547                         continue ;
01548                 else {
01549                         GList * attr_value_set = NULL ;
01550                         xmlAttribute *attr_desc = NULL ;
01551                         gint * last_id_ptr = NULL ;
01552                         gchar * default_value = NULL ;
01553                         xmlAttr * attr = NULL ;
01554 
01555                         if (a_node->doc && a_node->doc->intSubset)
01556                                 attr_desc = 
01557                                         xmlGetDtdAttrDesc (a_node->doc->intSubset,
01558                                                            a_node->name,
01559                                                            (gchar*)list_ptr->data) ;
01560 
01561                         if (attr_desc == NULL && a_node->doc && a_node->doc->extSubset)
01562                                 attr_desc =
01563                                         xmlGetDtdAttrDesc (a_node->doc->extSubset,
01564                                                            a_node->name,
01565                                                            (gchar*)list_ptr->data) ;
01566                         
01567                         if (attr_desc == NULL) /*attribute unknown by the dtd*/
01568                                 continue ;
01569                         
01570                         attr_desc->doc = a_node->doc ;
01571 
01572                         last_id_ptr = mlview_app_context_get_last_id_ptr (a_app_context) ;
01573 
01574                         if (last_id_ptr == NULL)
01575                                 continue ;
01576 
01577                         attr_value_set = 
01578                                 mlview_parsing_utils_build_attribute_value_set (a_app_context, 
01579                                                                                 attr_desc, last_id_ptr) ;
01580                         if (attr_value_set && attr_value_set->data)
01581                                 default_value = attr_value_set->data ;
01582                         else
01583                                 default_value = "defaultValue" ;
01584 
01585                         if (!xmlGetProp (a_node, (gchar*)list_ptr->data))
01586                                 attr = xmlSetProp (a_node, (gchar*)list_ptr->data,
01587                                                    default_value) ;
01588 
01589                         if (attr != NULL
01590                             &&attr_desc->atype == XML_ATTRIBUTE_ID
01591                             && a_node->doc) {
01592                                 xmlID * id = NULL ;
01593 
01594                                 if (a_node->doc->ids == NULL)
01595                                         a_node->doc->ids = xmlHashCreate (0) ;
01596 
01597                                 id = xmlMalloc (sizeof (xmlID)) ;
01598                                 g_assert (id != NULL) ;
01599                                 id->value = g_strdup (default_value) ;
01600                                 id->attr = attr ;
01601                                 xmlHashAddEntry (a_node->doc->ids, (const xmlChar *)default_value, id) ;
01602                         }
01603 
01604                         g_list_free (attr_value_set) ;
01605                         attr_value_set = NULL ;
01606                 }
01607         }
01608 
01609         return result ;
01610 }
01611 
01621 enum MLVIEW_PARSING_UTILS_STATUS
01622 mlview_parsing_utils_build_required_children_tree (MlViewAppContext * a_app_context,
01623                                                     xmlNode **a_node)
01624 {
01625         gchar * validation_is_on = NULL ;
01626         xmlElement * element_desc = NULL ;
01627         enum MLVIEW_PARSING_UTILS_STATUS status = NOK ;
01628 
01629         g_return_val_if_fail (a_app_context != NULL, BAD_PARAMETER) ;
01630         g_return_val_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context), BAD_PARAMETER) ;
01631         g_return_val_if_fail (a_node != NULL, BAD_PARAMETER) ;
01632         g_return_val_if_fail (*a_node != NULL, BAD_PARAMETER) ;
01633         g_return_val_if_fail ( ((*a_node)->type == XML_ELEMENT_NODE)
01634                                || ((*a_node)->type == XML_ATTRIBUTE_NODE),
01635                                BAD_PARAMETER) ;
01636 
01637         
01638 
01639         if (mlview_app_context_settings_exist (a_app_context) == FALSE)
01640                 return APP_SETTINGS_NOT_AVAILABLE ;
01641 
01642         validation_is_on = mlview_app_context_get_settings_value (a_app_context, MLVIEW_STG_K_IS_VALIDATION_ON) ;
01643 
01644         if (!validation_is_on 
01645             || strcmp (validation_is_on, MLVIEW_STG_V_YES))
01646                 return VALIDATION_IS_OFF ;
01647         
01648         g_return_val_if_fail ((*a_node)->doc != NULL, BAD_PARAMETER) ;
01649 
01650         g_return_val_if_fail (((*a_node)->doc->intSubset != NULL) 
01651                               || ((*a_node)->doc->extSubset != NULL) , 
01652                               BAD_PARAMETER) ;
01653         
01654         g_return_val_if_fail ( ((*a_node)->type == XML_ELEMENT_NODE),
01655                                BAD_PARAMETER) ;
01656         
01657         /*
01658         tmp_status = 
01659                 mlview_parsing_utils_build_element_name_completion_list (a_app_context, ADD_CHILD,
01660                                                                          (*a_node), 
01661                                                                          &feasible_children_names) ;
01662         if (tmp_status <= 0)
01663                 return NO_SUBTREE_REQUIRED_BY_SCHEMA ;
01664         g_return_val_if_fail (feasible_children_names != NULL, BAD_PARAMETER) ;
01665         */
01666         
01667         element_desc = 
01668                 xmlGetDtdElementDesc ((*a_node)->doc->intSubset, (*a_node)->name) ;
01669         
01670         if (!element_desc)
01671                 element_desc = 
01672                         xmlGetDtdElementDesc ((*a_node)->doc->extSubset,
01673                                               (*a_node)->name) ;
01674 
01675         g_return_val_if_fail (element_desc != NULL, 
01676                               ELEMENT_DESC_NOT_FOUND) ;
01677         
01678         if (!strcmp (element_desc->name, "#PCDATA")) {
01679                 xmlNodeSetContent (*a_node, "#PCDATA") ;
01680                 return OK ;
01681         }
01682 
01683         mlview_parsing_utils_build_required_attributes_list (a_app_context, *a_node) ;
01684 
01685         
01686         /*now, walk thru the element description tree to see what's going on there*/
01687         build_required_element_content (a_app_context, element_desc->content, a_node) ;
01688         
01689         return status ;
01690 }
01691 
01702 GList *
01703 mlview_parsing_utils_build_attribute_value_set (MlViewAppContext *a_app_context,
01704                                                 xmlAttribute * a_attribute_desc,
01705                                                 gint *a_last_id)
01706 {
01707         GList * result = NULL ;
01708         gchar * id_str = NULL ;
01709         /*xmlNode *a_node ;*/
01710         
01711         g_return_val_if_fail (a_app_context != NULL, NULL) ;
01712         g_return_val_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context), NULL) ;
01713 
01714         g_return_val_if_fail (a_attribute_desc != NULL, NULL) ;
01715         g_return_val_if_fail (a_attribute_desc->name != NULL, NULL) ;
01716         g_return_val_if_fail (a_attribute_desc->doc != NULL, NULL) ;
01717         
01718         g_return_val_if_fail (a_last_id != NULL, NULL) ;
01719 
01720         switch (a_attribute_desc->atype) {
01721 
01722         case XML_ATTRIBUTE_CDATA:
01723                 break ;
01724         case XML_ATTRIBUTE_ID:
01725                 if (a_attribute_desc->doc->ids == NULL)
01726                         a_attribute_desc->doc->ids = xmlHashCreate (0) ;
01727 
01728                 id_str = g_strdup_printf ("_%d", *a_last_id) ;
01729                 
01730                 while (xmlHashLookup (a_attribute_desc->doc->ids,
01731                                       id_str)) {
01732 
01733                         (*a_last_id) ++ ;
01734                         id_str = g_strdup_printf ("_%d", *a_last_id) ;
01735 
01736                 }
01737                 result = g_list_append (result,
01738                                         (gpointer)id_str) ;
01739                 break ;
01740         case XML_ATTRIBUTE_IDREF:
01741         case XML_ATTRIBUTE_IDREFS:
01742                 if (a_attribute_desc->doc->ids == NULL)
01743                         a_attribute_desc->doc->ids = xmlHashCreate (0) ;
01744 
01745                 xmlHashScan (a_attribute_desc->doc->ids,
01746                              (xmlHashScanner) mlview_parsing_utils_scan_and_build_ids_list,
01747                              &result) ;
01748                 break ;
01749         case XML_ATTRIBUTE_ENTITY:
01750         case XML_ATTRIBUTE_ENTITIES:
01751                 if (a_attribute_desc->doc->intSubset) {
01752                         xmlHashScan (a_attribute_desc->doc->intSubset->entities,
01753                                      (xmlHashScanner) mlview_parsing_utils_scan_and_build_entities_list,
01754                                      &result) ;
01755                 }
01756                 if (result == NULL
01757                     && a_attribute_desc->doc->extSubset) {
01758                         xmlHashScan (a_attribute_desc->doc->extSubset->entities,
01759                                      (xmlHashScanner) mlview_parsing_utils_scan_and_build_entities_list,
01760                                      &result) ;
01761                 }
01762 
01763                 break ;
01764         case XML_ATTRIBUTE_NMTOKEN:
01765         case XML_ATTRIBUTE_NMTOKENS:
01766                 break ;
01767         case XML_ATTRIBUTE_ENUMERATION:
01768                 if (a_attribute_desc->tree 
01769                     && a_attribute_desc->tree->name) {
01770                         xmlEnumeration * curr = a_attribute_desc->tree ;
01771                         while (curr) {
01772                                 if ( curr->name)
01773                                         result = g_list_append (result, 
01774                                                                 (gpointer) curr->name) ;
01775                                 curr = curr->next ;
01776                         }
01777                 }
01778                 break ;
01779         case XML_ATTRIBUTE_NOTATION:
01780                 break ;
01781         default :
01782                 break ;
01783         }
01784         return result ;
01785 }
01786 
01787 
01798 GList *
01799 mlview_parsing_utils_build_graphical_attribute_value_set (MlViewAppContext *a_app_context,
01800                                                           xmlAttribute * a_attribute_desc,
01801                                                           gint *a_last_id)
01802 {
01803         GList * result = NULL, *value_set ;
01804 
01805         g_return_val_if_fail (a_app_context != NULL, NULL) ;
01806         g_return_val_if_fail (MLVIEW_IS_APP_CONTEXT (a_app_context), NULL) ;
01807 
01808         g_return_val_if_fail (a_attribute_desc != NULL, NULL) ;
01809         g_return_val_if_fail (a_attribute_desc->name != NULL, NULL) ;
01810         g_return_val_if_fail (a_attribute_desc->doc != NULL, NULL) ;
01811 
01812         g_return_val_if_fail (a_last_id != NULL, NULL) ;
01813 
01814         value_set = 
01815                 mlview_parsing_utils_build_attribute_value_set (a_app_context,
01816                                                                 a_attribute_desc, 
01817                                                                 a_last_id) ;
01818         if (value_set) {
01819                 GList *list_ptr = NULL ;
01820 
01821                 for (list_ptr = value_set ; 
01822                      value_set; 
01823                      value_set = value_set->next) {
01824 
01825                         result = 
01826                                 g_list_append (result, 
01827                                                (gpointer)gtk_list_item_new_with_label ((gchar*)list_ptr->data)) ;
01828                 }
01829         }
01830                 
01831         return result ;
01832 }

Generated on Sat Jul 6 09:57:35 2002 for Gnome-MlView by doxygen1.2.16