]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikgotoxmltool.c
Add the storage and retrieval of any kind of track or waypoint selected item (either...
[andy/viking.git] / src / vikgotoxmltool.c
index 29de52c2430cd3eff30b14fab25775b1a88d9a66..e4db4d66cdfa33e307fd9afdc8099cb6c97475a1 100644 (file)
@@ -18,7 +18,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Created by Quy Tonthat <qtonthat@gmail.com>
  */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -53,7 +52,9 @@ struct _VikGotoXmlToolPrivate
 {
   gchar *url_format;
   gchar *lat_path;
+  gchar *lat_attr;
   gchar *lon_path;
+  gchar *lon_attr;
   
   struct LatLon ll;
 };
@@ -92,7 +93,9 @@ enum
 
   PROP_URL_FORMAT,
   PROP_LAT_PATH,
+  PROP_LAT_ATTR,
   PROP_LON_PATH,
+  PROP_LON_ATTR,
 };
 
 static void
@@ -103,6 +106,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 +116,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 +191,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 +233,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",
                                "<no-set>" /* default value */,
                                G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
@@ -189,8 +241,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",
                                "<no-set>" /* default value */,
                                G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
@@ -198,6 +259,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 +286,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 +328,46 @@ stack_is_path (const GSList *stack,
   return equal;
 }
 
+/* Called for open tags <foo bar="baz"> */
+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 +382,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 +397,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 +435,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)