X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/0c6b26d31b0d192fe8715244b25b426658e67063..e96fe99dfb8c926ba4c6ee558380cc3f7f5241bc:/src/vikgotoxmltool.c diff --git a/src/vikgotoxmltool.c b/src/vikgotoxmltool.c index 29de52c2..d0b6a009 100644 --- a/src/vikgotoxmltool.c +++ b/src/vikgotoxmltool.c @@ -53,7 +53,9 @@ struct _VikGotoXmlToolPrivate { gchar *url_format; gchar *lat_path; + gchar *lat_attr; gchar *lon_path; + gchar *lon_attr; struct LatLon ll; }; @@ -92,7 +94,9 @@ enum PROP_URL_FORMAT, PROP_LAT_PATH, + PROP_LAT_ATTR, PROP_LON_PATH, + PROP_LON_ATTR, }; static void @@ -103,6 +107,7 @@ _goto_xml_tool_set_property (GObject *object, { VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (object); VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self); + gchar **splitted = NULL; switch (property_id) { @@ -112,13 +117,53 @@ _goto_xml_tool_set_property (GObject *object, break; case PROP_LAT_PATH: + splitted = g_strsplit (g_value_get_string (value), "@", 2); g_free (priv->lat_path); - priv->lat_path = g_value_dup_string (value); + priv->lat_path = splitted[0]; + if (splitted[1]) + { + g_object_set (object, "lat-attr", splitted[1], NULL); + g_free (splitted[1]); + } + /* only free the tab, not the strings */ + g_free (splitted); + splitted = NULL; + break; + + case PROP_LAT_ATTR: + /* Avoid to overwrite XPATH value */ + /* NB: This disable future overwriting, + but as property is CONSTRUCT_ONLY there is no matter */ + if (!priv->lat_attr || g_value_get_string (value)) + { + g_free (priv->lat_attr); + priv->lat_attr = g_value_dup_string (value); + } break; case PROP_LON_PATH: + splitted = g_strsplit (g_value_get_string (value), "@", 2); g_free (priv->lon_path); - priv->lon_path = g_value_dup_string (value); + priv->lon_path = splitted[0]; + if (splitted[1]) + { + g_object_set (object, "lon-attr", splitted[1], NULL); + g_free (splitted[1]); + } + /* only free the tab, not the strings */ + g_free (splitted); + splitted = NULL; + break; + + case PROP_LON_ATTR: + /* Avoid to overwrite XPATH value */ + /* NB: This disable future overwriting, + but as property is CONSTRUCT_ONLY there is no matter */ + if (!priv->lon_attr || g_value_get_string (value)) + { + g_free (priv->lon_attr); + priv->lon_attr = g_value_dup_string (value); + } break; default: @@ -147,10 +192,18 @@ _goto_xml_tool_get_property (GObject *object, g_value_set_string (value, priv->lat_path); break; + case PROP_LAT_ATTR: + g_value_set_string (value, priv->lat_attr); + break; + case PROP_LON_PATH: g_value_set_string (value, priv->lon_path); break; + case PROP_LON_ATTR: + g_value_set_string (value, priv->lon_attr); + break; + default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -181,7 +234,7 @@ static void _goto_xml_tool_class_init ( VikGotoXmlToolClass *klass ) pspec); pspec = g_param_spec_string ("lat-path", - "Lat path", + "Latitude path", "XPath of the latitude", "" /* default value */, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); @@ -189,8 +242,17 @@ static void _goto_xml_tool_class_init ( VikGotoXmlToolClass *klass ) PROP_LAT_PATH, pspec); + pspec = g_param_spec_string ("lat-attr", + "Latitude attribute", + "XML attribute of the latitude", + NULL /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (object_class, + PROP_LAT_ATTR, + pspec); + pspec = g_param_spec_string ("lon-path", - "Lon path", + "Longitude path", "XPath of the longitude", "" /* default value */, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); @@ -198,6 +260,15 @@ static void _goto_xml_tool_class_init ( VikGotoXmlToolClass *klass ) PROP_LON_PATH, pspec); + pspec = g_param_spec_string ("lon-attr", + "Longitude attribute", + "XML attribute of the longitude", + NULL /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (object_class, + PROP_LON_ATTR, + pspec); + parent_class = VIK_GOTO_TOOL_CLASS (klass); parent_class->get_url_format = _goto_xml_tool_get_url_format; @@ -216,7 +287,9 @@ static void _goto_xml_tool_init ( VikGotoXmlTool *self ) VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self); priv->url_format = NULL; priv->lat_path = NULL; + priv->lat_attr = NULL; priv->lon_path = NULL; + priv->lon_attr = NULL; // priv->ll.lat = NAN; priv->ll.lon = NAN; @@ -256,6 +329,46 @@ stack_is_path (const GSList *stack, return equal; } +/* Called for open tags */ +static void +_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + VikGotoXmlTool *self = VIK_GOTO_XML_TOOL (user_data); + VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self); + const GSList *stack = g_markup_parse_context_get_element_stack (context); + /* Longitude */ + if (priv->lon_attr != NULL && isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path)) + { + int i=0; + while (attribute_names[i] != NULL) + { + if (strcmp (attribute_names[i], priv->lon_attr) == 0) + { + priv->ll.lon = g_ascii_strtod(attribute_values[i], NULL); + } + i++; + } + } + /* Latitude */ + if (priv->lat_attr != NULL && isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path)) + { + int i=0; + while (attribute_names[i] != NULL) + { + if (strcmp (attribute_names[i], priv->lat_attr) == 0) + { + priv->ll.lat = g_ascii_strtod(attribute_values[i], NULL); + } + i++; + } + } +} + /* Called for character data */ /* text is not nul-terminated */ static void @@ -270,11 +383,11 @@ _text (GMarkupParseContext *context, const GSList *stack = g_markup_parse_context_get_element_stack (context); gchar *textl = g_strndup(text, text_len); /* Store only first result */ - if (isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path)) + if (priv->lat_attr == NULL && isnan(priv->ll.lat) && stack_is_path (stack, priv->lat_path)) { priv->ll.lat = g_ascii_strtod(textl, NULL); } - if (isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path)) + if (priv->lon_attr == NULL && isnan(priv->ll.lon) && stack_is_path (stack, priv->lon_path)) { priv->ll.lon = g_ascii_strtod(textl, NULL); } @@ -285,20 +398,33 @@ static gboolean _goto_xml_tool_parse_file_for_latlon(VikGotoTool *self, gchar *filename, struct LatLon *ll) { GMarkupParser xml_parser; - GMarkupParseContext *xml_context; - GError *error; + GMarkupParseContext *xml_context = NULL; + GError *error = NULL; VikGotoXmlToolPrivate *priv = GOTO_XML_TOOL_GET_PRIVATE (self); g_return_val_if_fail(priv != NULL, FALSE); + g_debug ("%s: %s@%s, %s@%s", + __FUNCTION__, + priv->lat_path, priv->lat_attr, + priv->lon_path, priv->lon_attr); + FILE *file = g_fopen (filename, "r"); if (file == NULL) /* TODO emit warning */ return FALSE; /* setup context parse (ie callbacks) */ - xml_parser.start_element = NULL; + if (priv->lat_attr != NULL || priv->lon_attr != NULL) + // At least one coordinate uses an attribute + xml_parser.start_element = &_start_element; + else + xml_parser.start_element = NULL; xml_parser.end_element = NULL; - xml_parser.text = &_text; + if (priv->lat_attr == NULL || priv->lon_attr == NULL) + // At least one coordinate uses a raw element + xml_parser.text = &_text; + else + xml_parser.text = NULL; xml_parser.passthrough = NULL; xml_parser.error = NULL; @@ -310,16 +436,28 @@ _goto_xml_tool_parse_file_for_latlon(VikGotoTool *self, gchar *filename, struct gchar buff[BUFSIZ]; size_t nb; - while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0) + while (xml_context && + (nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0) { if (!g_markup_parse_context_parse(xml_context, buff, nb, &error)) - fprintf(stderr, "%s: parsing error.\n", __FUNCTION__); + { + fprintf(stderr, "%s: parsing error: %s.\n", + __FUNCTION__, error->message); + g_markup_parse_context_free(xml_context); + xml_context = NULL; + } + g_clear_error (&error); } /* cleanup */ - if (!g_markup_parse_context_end_parse(xml_context, &error)) - fprintf(stderr, "%s: errors occurred reading file.\n", __FUNCTION__); + if (xml_context && + !g_markup_parse_context_end_parse(xml_context, &error)) + fprintf(stderr, "%s: errors occurred while reading file: %s.\n", + __FUNCTION__, error->message); + g_clear_error (&error); - g_markup_parse_context_free(xml_context); + if (xml_context) + g_markup_parse_context_free(xml_context); + xml_context = NULL; fclose (file); if (ll != NULL)