Example #1
0
gchar *
xml_reader_read_string (XmlReader *reader)
{
  g_return_val_if_fail (XML_IS_READER (reader), NULL);
  g_return_val_if_fail (reader->xml != NULL, NULL);

  RETURN_STRDUP_AND_XMLFREE (xmlTextReaderReadString (reader->xml));
}
static void
biji_process_string (xmlTextReaderPtr reader,
                     BijiReaderFunc process_xml,
                     gpointer user_data)
{
  xmlChar *result = xmlTextReaderReadString (reader);
  process_xml (BIJI_NOTE_OBJ (user_data), (gchar*) result);
  free (result);
}
Example #3
0
/* reader:read_string() */
static int xmlreader_read_string(lua_State *L) {
  xmlreader xr = check_xmlreader(L, 1);
  char *str = (char*)xmlTextReaderReadString(xr);
  if (str) {
    lua_pushstring(L, str);
    xmlFree(str);
    return 1;
  } else {
    lua_pushnil(L);
    lua_pushstring(L, "not positioned on element or text node");
    return 2;
  }
}
Example #4
0
/*
 * call-seq:
 *    reader.read_string -> string
 *
 * Read the contents of an element or a text node as a string.
 *
 * Return a string containing the contents of the Element or Text node, or nil
 * if the reader is positioned on any other type of node.
 */
static VALUE rxml_reader_read_string(VALUE self)
{
  VALUE result = Qnil;
  xmlTextReaderPtr xReader = rxml_text_reader_get(self);

  xmlChar *xml = xmlTextReaderReadString(xReader);

  if (xml)
  {
    const xmlChar *xencoding = xmlTextReaderConstEncoding(xReader);
    result = rxml_new_cstr((const char*) xml, xencoding);
    xmlFree(xml);
  }

  return result;
}
Example #5
0
static void processNode(xmlTextReaderPtr reader, Buffer * buf) {
	int type = xmlTextReaderNodeType(reader);

	if (type == XML_TEXT_NODE) {
		unsigned char *s = xmlTextReaderReadString(reader);
		int slen = strlen(s);
		char enc[512];
		int enclen = 512;
		if (!htmlEncodeEntities(enc, &enclen, s, &slen, 0)) {
			buffer_in(buf, enc, enclen);

			if (enc[enclen-1] != ' ') {
				buffer_in(buf, " ", 1);
			}
		}

		free(s);
	}
}
Example #6
0
queryFavouriteFolder::queryFavouriteFolder(xmlTextReaderPtr reader, wxString title) : queryFavouriteItem(title, wxT(""))
{
	id = -2;

	// Element of type <foo />, meaning empty folder
	if (xmlTextReaderIsEmptyElement(reader))
		return;

	while (xmlTextReaderRead(reader))
	{
		int type = xmlTextReaderNodeType(reader);

		if (type == 15)
			return; // Close on parent element
		if (xmlTextReaderNodeType(reader) != 1)
			continue; // Any unknown element type

		wxString nodename = WXSTRING_FROM_XML(xmlTextReaderConstName(reader));

		xmlChar *ctitle = xmlTextReaderGetAttribute(reader, XML_STR("title"));
		if (!ctitle)
			continue; // We ignore nodes without title
		wxString title = WXSTRING_FROM_XML(ctitle);
		xmlFree(ctitle);

		if (nodename == wxT("favourite"))
		{
			xmlChar *cont = xmlTextReaderReadString(reader);
			if (!cont)
				continue; // No contents, so ignore node

			favourites.Add(new queryFavouriteItem(title, WXSTRING_FROM_XML(cont)));
			xmlFree(cont);
			SkipToEndElement(reader);
		}
		else if (nodename == wxT("folder"))
		{
			favourites.Add(new queryFavouriteFolder(reader, title));
		}
	}
}
Example #7
0
queryMacroList::queryMacroList(xmlTextReaderPtr reader)
{
	// Element of type <foo />, meaning empty folder
	if (xmlTextReaderIsEmptyElement(reader))
		return;

	while (xmlTextReaderRead(reader))
	{
		int type = xmlTextReaderNodeType(reader);

		if (type == 15)
			return; // Close on parent element
		if (xmlTextReaderNodeType(reader) != 1)
			continue; // Any unknown element type

		wxString nodename = WXSTRING_FROM_XML(xmlTextReaderConstName(reader));

		xmlChar *ckey = xmlTextReaderGetAttribute(reader, XML_STR("key"));
		if (!ckey)
			continue;
		wxString key = WXSTRING_FROM_XML(ckey);
		xmlFree(ckey);

		xmlChar *cname = xmlTextReaderGetAttribute(reader, XML_STR("name"));
		if (!cname)
			continue;
		wxString name = WXSTRING_FROM_XML(cname);
		xmlFree(cname);

		if (nodename == wxT("macro"))
		{
			xmlChar *cquery = xmlTextReaderReadString(reader);
			if (!cquery)
				continue;
			wxString query = WXSTRING_FROM_XML(cquery);
			xmlFree(cquery);
			macros.Add(new queryMacroItem(key, name, query));
			SkipToEndElement(reader);
		}
	}
}
Example #8
0
/*
 * call-seq:
 *    reader.read_string -> string
 *
 * Read the contents of an element or a text node as a string.
 *
 * Return a string containing the contents of the Element or Text node, or nil
 * if the reader is positioned on any other type of node.
 */
static VALUE rxml_reader_read_string(VALUE self)
{
  const xmlChar *result = xmlTextReaderReadString(rxml_text_reader_get(self));
  return (result == NULL ? Qnil : rb_str_new2((const char*)result));
}
static response_element_t *
parse_response_tag (const parser_strings_t *strings,
                    xmlTextReaderPtr reader)
{
	xmlChar            *href  = NULL;
	xmlChar            *etag  = NULL;
	gint                 depth = xmlTextReaderDepth (reader);
	response_element_t *element;

	while (xmlTextReaderRead (reader) == 1 && xmlTextReaderDepth (reader) > depth) {
		const xmlChar *tag_name;
		if (xmlTextReaderNodeType (reader) != XML_READER_TYPE_ELEMENT)
			continue;

		if (xmlTextReaderConstNamespaceUri (reader) != strings->dav)
			continue;

		tag_name = xmlTextReaderConstLocalName (reader);
		if (tag_name == strings->href) {
			if (href != NULL) {
				/* multiple href elements?!? */
				xmlFree (href);
			}
			href = xmlTextReaderReadString (reader);
		} else if (tag_name == strings->propstat) {
			/* find <propstat><prop><getetag> hierarchy */
			gint depth2 = xmlTextReaderDepth (reader);
			while (xmlTextReaderRead (reader) == 1 && xmlTextReaderDepth (reader) > depth2) {
				gint depth3;
				if (xmlTextReaderNodeType (reader) != XML_READER_TYPE_ELEMENT)
					continue;

				if (xmlTextReaderConstNamespaceUri (reader) != strings->dav
						|| xmlTextReaderConstLocalName (reader) != strings->prop)
					continue;

				depth3 = xmlTextReaderDepth (reader);
				while (xmlTextReaderRead (reader) == 1 && xmlTextReaderDepth (reader) > depth3) {
					if (xmlTextReaderNodeType (reader) != XML_READER_TYPE_ELEMENT)
						continue;

					if (xmlTextReaderConstNamespaceUri (reader) != strings->dav
							|| xmlTextReaderConstLocalName (reader)
							!= strings->getetag)
						continue;

					if (etag != NULL) {
						/* multiple etag elements?!? */
						xmlFree (etag);
					}
					etag = xmlTextReaderReadString (reader);
				}
			}
		}
	}

	if (href == NULL) {
		g_warning ("webdav returned response element without href");
		return NULL;
	}

	/* append element to list */
	element = g_malloc (sizeof (element[0]));
	element->href = href;
	element->etag = etag;
	return element;
}
/* Common XML format for both Bijiben / Tomboy */
static void
processNode (BijiLazyDeserializer *self) 
{
  xmlTextReaderPtr r = self->priv->r;
  BijiNoteObj * n = self->priv->note;
  xmlChar   *name;
  GdkRGBA   *color;
  gchar     *tag;
  GString   *norm;
  gchar     *debug;

  name = xmlTextReaderName (r);

  if ( g_strcmp0((gchar*)name,"title") == 0 )
    biji_process_string (r, (BijiReaderFunc*) biji_note_obj_set_title, n);

  if ( g_strcmp0((gchar*)name,"text") == 0 )
  {
    if (self->priv->type == BIJIBEN_1)
    {
      self->priv->content = (gchar*) xmlTextReaderReadInnerXml (r);
      process_bijiben_html_content (self);
    }

    else if (self->priv->type == TOMBOY_1 ||
             self->priv->type == TOMBOY_2 ||
             self->priv->type == TOMBOY_3 )
    {
      self->priv->content = (gchar*) xmlTextReaderReadInnerXml (r);
      process_tomboy_xml_content (self);
    }
  }

  if (g_strcmp0 ((gchar*) name, "last-change-date") == 0)
    biji_process_string (r, (BijiReaderFunc*) biji_note_obj_set_last_change_date, n); 

  if (g_strcmp0 ((gchar*) name, "last-metadata-change-date") == 0)
    biji_process_string (r, (BijiReaderFunc*) biji_note_obj_set_last_metadata_change_date, n); 

  if (g_strcmp0 ((gchar*) name, "create-date") == 0)
    biji_process_string (r, (BijiReaderFunc*) biji_note_obj_set_create_date, n); 

  if (g_strcmp0 ((gchar*) name, "color") == 0 )  
  {
    color = g_new (GdkRGBA,1);
    debug = (gchar*) xmlTextReaderReadString (r);

    if ( gdk_rgba_parse (color,debug))
    {
      biji_note_obj_set_rgba (n, color);
    }
    else
    {
      g_warning ("color invalid:%s",debug);
    }

    free (debug);

  }

  if ( g_strcmp0((gchar*)name,"tag") == 0 )  
  {
    tag = (gchar*) xmlTextReaderReadString(r);

    if (g_str_has_prefix (tag,"system:template"))
    {
      note_obj_set_is_template(n,TRUE);
    }

    else if (g_str_has_prefix (tag,"system:notebook:"))
    {
      norm = g_string_new (tag);
      g_string_erase (norm,0,16);
      _biji_note_obj_set_tags (n, g_list_prepend((GList*)_biji_note_obj_get_tags(n),
                               g_string_free (norm,FALSE)));
    }

    free (tag);
  }

  xmlFree(name);
}
Example #11
0
bool IWORKParser::parse()
{
  const shared_ptr<xmlTextReader> sharedReader(xmlReaderForIO(readFromStream, closeStream, m_input.get(), "", nullptr, 0), xmlFreeTextReader);
  if (!sharedReader)
    return false;

  xmlTextReaderPtr reader = sharedReader.get();
  assert(reader);

  const IWORKTokenizer &tokenizer = getTokenizer();
  stack<IWORKXMLContextPtr_t> contextStack;

  int ret = xmlTextReaderRead(reader);
  contextStack.push(createDocumentContext());

  bool keynoteDocTypeChecked=false;
  char const *defaultNS=nullptr;
  while ((1 == ret))
  {
    switch (xmlTextReaderNodeType(reader))
    {
    case XML_READER_TYPE_ELEMENT:
    {
      if (!keynoteDocTypeChecked)
      {
        // check for keynote 1 file with doctype node and not a namespace in first node
        keynoteDocTypeChecked=true;
        if (xmlTextReaderNodeType(reader)==XML_READER_TYPE_ELEMENT &&
            xmlTextReaderConstNamespaceUri(reader)==nullptr)
          defaultNS="http://developer.apple.com/schemas/APXL";
      }
      const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)),
                                              defaultNS ? defaultNS : char_cast(xmlTextReaderConstNamespaceUri(reader)));

      IWORKXMLContextPtr_t newContext = contextStack.top()->element(id);

      if (!newContext)
        newContext = createDiscardContext();

      const bool isEmpty = xmlTextReaderIsEmptyElement(reader);

      newContext->startOfElement();
      if (xmlTextReaderHasAttributes(reader))
      {
        ret = xmlTextReaderMoveToFirstAttribute(reader);
        while (1 == ret)
        {
          processAttribute(reader, newContext, tokenizer);
          ret = xmlTextReaderMoveToNextAttribute(reader);
        }
      }

      if (isEmpty)
        newContext->endOfElement();
      else
        contextStack.push(newContext);

      break;
    }
    case XML_READER_TYPE_END_ELEMENT:
    {
      contextStack.top()->endOfElement();
      contextStack.pop();
      break;
    }
    case XML_READER_TYPE_CDATA :
    {
      const xmlChar *text = xmlTextReaderConstValue(reader);
      if (text) contextStack.top()->CDATA(char_cast(text));
      break;
    }
    case XML_READER_TYPE_TEXT :
    {
      xmlChar *const text = xmlTextReaderReadString(reader);
      contextStack.top()->text(char_cast(text));
      xmlFree(text);
      break;
    }
    default:
      break;
    }

    ret = xmlTextReaderRead(reader);

  }

  while (!contextStack.empty()) // finish parsing in case of broken XML
  {
    contextStack.top()->endOfElement();
    contextStack.pop();
  }
  xmlTextReaderClose(reader);

  return true;
}
Example #12
0
bool IWORKParser::parse()
{
  const shared_ptr<xmlTextReader> sharedReader(xmlReaderForIO(readFromStream, closeStream, m_input.get(), "", 0, 0), xmlFreeTextReader);
  if (!sharedReader)
    return false;

  xmlTextReaderPtr reader = sharedReader.get();
  assert(reader);

  const IWORKTokenizer &tokenizer = getTokenizer();
  stack<IWORKXMLContextPtr_t> contextStack;

  int ret = xmlTextReaderRead(reader);
  contextStack.push(createDocumentContext());

  while ((1 == ret))
  {
    switch (xmlTextReaderNodeType(reader))
    {
    case XML_READER_TYPE_ELEMENT:
    {
      const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));

      IWORKXMLContextPtr_t newContext = contextStack.top()->element(id);

      if (!newContext)
        newContext = createDiscardContext();

      const bool isEmpty = xmlTextReaderIsEmptyElement(reader);

      newContext->startOfElement();
      if (xmlTextReaderHasAttributes(reader))
      {
        ret = xmlTextReaderMoveToFirstAttribute(reader);
        while (1 == ret)
        {
          processAttribute(reader, newContext, tokenizer);
          ret = xmlTextReaderMoveToNextAttribute(reader);
        }
      }

      if (isEmpty)
        newContext->endOfElement();
      else
        contextStack.push(newContext);

      break;
    }
    case XML_READER_TYPE_END_ELEMENT:
    {
      contextStack.top()->endOfElement();
      contextStack.pop();
      break;
    }
    case XML_READER_TYPE_TEXT :
    {
      xmlChar *const text = xmlTextReaderReadString(reader);
      contextStack.top()->text(char_cast(text));
      xmlFree(text);
      break;
    }
    default:
      break;
    }

    ret = xmlTextReaderRead(reader);

  }

  while (!contextStack.empty()) // finish parsing in case of broken XML
  {
    contextStack.top()->endOfElement();
    contextStack.pop();
  }
  xmlTextReaderClose(reader);

  return true;
}
Example #13
0
/* Common XML format for both Bijiben / Tomboy */
static void
processNode (BijiLazyDeserializer *self) 
{
  xmlTextReaderPtr r = self->priv->r;
  BijiNoteObj * n = self->priv->note;
  xmlChar   *name;
  GdkRGBA    color;
  gchar     *tag, *color_str;
  GString   *norm;

  name = xmlTextReaderName (r);

  if ( g_strcmp0((gchar*)name,"title") == 0 )
    biji_process_string (r, (BijiReaderFunc*) biji_note_obj_set_title, n);

  if ( g_strcmp0((gchar*)name,"text") == 0 )
  {
    if (self->priv->type == BIJIBEN_1)
    {
      process_bijiben_html_content (self, r);
    }

    else if (self->priv->type == TOMBOY_1 ||
             self->priv->type == TOMBOY_2 ||
             self->priv->type == TOMBOY_3 )
    {
      self->priv->content = (gchar*) xmlTextReaderReadInnerXml (r);
      process_tomboy_xml_content (self);
    }
  }

  if (g_strcmp0 ((gchar*) name, "last-change-date") == 0)
  {
    gchar *result = (gchar*) xmlTextReaderReadString (r);
    biji_note_obj_set_mtime (n, iso8601_to_gint64 (result));
    free (result);
  }

  if (g_strcmp0 ((gchar*) name, "last-metadata-change-date") == 0)
  {
    gchar *result = (gchar*) xmlTextReaderReadString (r);
    biji_note_obj_set_last_metadata_change_date (n, iso8601_to_gint64 (result));
    free (result);
  }

  if (g_strcmp0 ((gchar*) name, "create-date") == 0)
  {
    gchar *result = (gchar*) xmlTextReaderReadString (r);
    biji_note_obj_set_create_date (n, iso8601_to_gint64 (result));
    free (result);
  }

  if (g_strcmp0 ((gchar*) name, "color") == 0 )  
  {
    color_str = (gchar*) xmlTextReaderReadString (r);

    if (gdk_rgba_parse (&color, color_str))
      biji_note_obj_set_rgba (n, &color);

    else
      g_warning ("color invalid:%s", color_str);

    free (color_str);
  }

  if ( g_strcmp0((gchar*)name,"tag") == 0 )  
  {
    tag = (gchar*) xmlTextReaderReadString(r);

    if (g_str_has_prefix (tag,"system:template"))
    {
      note_obj_set_is_template(n,TRUE);
    }

    else if (g_str_has_prefix (tag,"system:notebook:"))
    {
      norm = g_string_new (tag);
      g_string_erase (norm,0,16);
      biji_item_add_notebook (BIJI_ITEM (n), NULL, norm->str);
      g_string_free (norm, TRUE);
    }

    free (tag);
  }

  xmlFree(name);
}
Example #14
0
void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
{
    char * value;
    float version;
    int isAddressLine;

    if (fileType == FILETYPE_NONE)
    {
        // Potential to handle other file types in the future / versions
        if (xmlStrEqual(name, BAD_CAST "osmStructured"))
        {
            value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "version");
            version = strtof(value, NULL);
            xmlFree(value);

            if (version == (float)0.1)
            {
                fileType = FILETYPE_STRUCTUREDV0P1;
                fileMode = FILEMODE_ADD;
            }
            else
            {
                fprintf( stderr, "Unknown osmStructured version %f (%s)\n", version, value );
                exit_nicely();
            }
        }
        else
        {
            fprintf( stderr, "Unknown XML document type: %s\n", name );
            exit_nicely();
        }
        return;
    }

    if (xmlStrEqual(name, BAD_CAST "add"))
    {
        fileMode = FILEMODE_ADD;
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "update"))
    {
        fileMode = FILEMODE_UPDATE;
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "delete"))
    {
        fileMode = FILEMODE_DELETE;
        return;
    }
    if (fileMode == FILEMODE_NONE)
    {
        fprintf( stderr, "Unknown import mode in: %s\n", name );
        exit_nicely();
    }

    if (xmlStrEqual(name, BAD_CAST "feature"))
    {
        feature.placeID = xmlTextReaderGetAttribute(reader, BAD_CAST "place_id");
        feature.type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
        feature.id = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
        feature.key = xmlTextReaderGetAttribute(reader, BAD_CAST "key");
        feature.value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
        feature.rankAddress = xmlTextReaderGetAttribute(reader, BAD_CAST "rank");
        feature.rankSearch = xmlTextReaderGetAttribute(reader, BAD_CAST "importance");

        feature.parentPlaceID = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_place_id");
/*
	if (strlen(feature.parentPlaceID) == 0)
	{
		xmlFree(feature.parentPlaceID);
		feature.parentPlaceID = NULL;
	}
*/
        feature.parentType = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_type");
        feature.parentID = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_id");

        feature.countryCode = NULL;
        feature.adminLevel = NULL;
        feature.houseNumber = NULL;
        feature.geometry = NULL;
        featureAddressLines = 0;
        featureNameLines = 0;
        featureExtraTagLines = 0;

        return;
    }
    if (xmlStrEqual(name, BAD_CAST "names")) return;
    if (xmlStrEqual(name, BAD_CAST "name"))
    {
        if (featureNameLines < MAX_FEATURENAMES)
        {
	        featureName[featureNameLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
    	    featureName[featureNameLines].value = xmlTextReaderReadString(reader);
        	featureNameLines++;
		}
		else
		{
            fprintf( stderr, "Too many name elements (%s%s)\n", feature.type, feature.id);
//            exit_nicely();
        }
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "tags")) return;
    if (xmlStrEqual(name, BAD_CAST "tag"))
    {
        if (featureExtraTagLines < MAX_FEATUREEXTRATAGS)
		{
	        featureExtraTag[featureExtraTagLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
    	    featureExtraTag[featureExtraTagLines].value = xmlTextReaderReadString(reader);
        	featureExtraTagLines++;
		}
		else
        {
            fprintf( stderr, "Too many extra tag elements (%s%s)\n", feature.type, feature.id);
//            exit_nicely();
        }
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "osmGeometry"))
    {
        feature.geometry = xmlTextReaderReadString(reader);
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "adminLevel"))
    {
        feature.adminLevel = xmlTextReaderReadString(reader);
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "countryCode"))
    {
        feature.countryCode = xmlTextReaderReadString(reader);
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "houseNumber"))
    {
        feature.houseNumber = xmlTextReaderReadString(reader);
        return;
    }
    if (xmlStrEqual(name, BAD_CAST "address"))
    {
        featureAddressLines = 0;
        return;
    }
    isAddressLine = 0;
    if (xmlStrEqual(name, BAD_CAST "continent"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "sea"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "country"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "state"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "county"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "city"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "town"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "village"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "unknown"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "suburb"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "postcode"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "neighborhood"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "street"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "access"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "building"))
    {
        isAddressLine = 1;
    }
    else if (xmlStrEqual(name, BAD_CAST "other"))
    {
        isAddressLine = 1;
    }
    if (isAddressLine)
    {
        if (featureAddressLines < MAX_FEATUREADDRESS)
		{
	        value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "rank");
    	    if (!value)
	        {
    	        fprintf( stderr, "Address element missing rank\n");
        	    exit_nicely();
	        }
    	    featureAddress[featureAddressLines].rankAddress =  atoi(value);
        	xmlFree(value);

	        value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "isaddress");
    	    if (!value)
        	{
	            fprintf( stderr, "Address element missing rank\n");
    	        exit_nicely();
        	}
	        if (*value == 't') strcpy(featureAddress[featureAddressLines].isAddress, "t");
    	    else strcpy(featureAddress[featureAddressLines].isAddress, "f");
        	xmlFree(value);

	        featureAddress[featureAddressLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
    	    featureAddress[featureAddressLines].id = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
        	featureAddress[featureAddressLines].key = xmlTextReaderGetAttribute(reader, BAD_CAST "key");
	        featureAddress[featureAddressLines].value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
    	    featureAddress[featureAddressLines].distance = xmlTextReaderGetAttribute(reader, BAD_CAST "distance");
	
    	    featureAddressLines++;
		}
		else
        {
            fprintf( stderr, "Too many address elements (%s%s)\n", feature.type, feature.id);
//            exit_nicely();
        }

        return;
    }
    fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
}