4

I making a java application that give the user notification with the weather conditions. i used the yahoo weather API provided by yahoo like that link :

http://weather.yahooapis.com/forecastrss?w=2502265

and all i have to do is to change the eight numbered code that is in the URL in order to change the city.

that's working perfect, but there are two problems facing me now:

the first one, i want to implement a lot of weather forecast sources in my application not just the yahoo weather and i can't find a similar service in any other weather forecast websites.

the second one, i want to obtain the codes of all the cities in yahoo weather as for sure i won't ask the user to enter his city code, but to enter his city name and i'll match it with the code.

and here is the code that works with me in java:

the code to return the XML file:

package search;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;

    public class Process {

        public static void main(String[] args) throws IOException {

            Display disp = new Display();

            Document doc = generateXML("1940345");
            disp.getConditions(doc);

        }

        public static Document generateXML(String code) throws IOException {

            String url = null;
            String XmlData = null;

            // creating the URL
            url = "http://weather.yahooapis.com/forecastrss?w=" + code;
            URL xmlUrl = new URL(url);
            InputStream in = xmlUrl.openStream();

            // parsing the XmlUrl
            Document doc = parse(in);

            return doc;

        }

        public static Document parse(InputStream is) {
            Document doc = null;
            DocumentBuilderFactory domFactory;
            DocumentBuilder builder;

            try {
                domFactory = DocumentBuilderFactory.newInstance();
                domFactory.setValidating(false);
                domFactory.setNamespaceAware(false);
                builder = domFactory.newDocumentBuilder();

                doc = builder.parse(is);
            } catch (Exception ex) {
                System.err.println("unable to load XML: " + ex);
            }
            return doc;
        }
    }

the code to display the temperature and humidity in that city :

package search;

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Display {

    static void getConditions(Document doc) {

        String city = null;
        String unit = null;

        try {

            doc.getDocumentElement().normalize();

            NodeList nList = doc.getElementsByTagName("rss");

            for (int temp = 0; temp < nList.getLength(); temp++) {

                Node nNode = nList.item(temp);

                if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                    Element eElement = (Element) nNode;

                    NodeList nl = eElement
                            .getElementsByTagName("yweather:location");

                    for (int tempr = 0; tempr < nl.getLength(); tempr++) {

                        Node n = nl.item(tempr);

                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                            Element e = (Element) n;
                            city = e.getAttribute("city");
                            System.out.println("The City Is : " + city);

                        }
                    }

                    NodeList nl2 = eElement
                            .getElementsByTagName("yweather:units");

                    for (int tempr = 0; tempr < nl2.getLength(); tempr++) {

                        Node n2 = nl2.item(tempr);

                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                            Element e2 = (Element) n2;
                            unit = e2.getAttribute("temperature");

                        }
                    }

                    NodeList nl3 = eElement
                            .getElementsByTagName("yweather:condition");

                    for (int tempr = 0; tempr < nl3.getLength(); tempr++) {

                        Node n3 = nl3.item(tempr);

                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                            Element e3 = (Element) n3;
                            System.out.println("The Temperature In " + city
                                    + " Is : " + e3.getAttribute("temp") + " "
                                    + unit);
                        }
                    }

                    NodeList nl4 = eElement
                            .getElementsByTagName("yweather:atmosphere");

                    for (int tempr = 0; tempr < nl4.getLength(); tempr++) {

                        Node n4 = nl4.item(tempr);

                        if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                            Element e4 = (Element) n4;
                            System.out.println("The Humidity In " + city
                                    + " Is : " + e4.getAttribute("humidity"));
                        }
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
Muhammed Refaat
  • 8,914
  • 14
  • 83
  • 118

6 Answers6

2

You can use Metwit weather api simply passing latitude and longitude.
If you can implement them client-side: 200 request/day (ip based throttling) no authentication required. Worldwide coverage, JSON and REST compliant. You can register for extra API calls for free and if you still need it to call them server side the basic plan is pretty cheap.

Full disclosure: I own this API.

beddamadre
  • 1,583
  • 2
  • 19
  • 40
1

Take a look on this discussion. It seems relevant:

https://stackoverflow.com/questions/4876800/is-there-an-international-weather-forecast-api-that-is-not-limited-for-non-comme

Additionally type "weather forecast api" in google. There are tons of references to APIs that support several weather services.

Community
  • 1
  • 1
AlexR
  • 114,158
  • 16
  • 130
  • 208
  • for sure i have tried to do that, but i didn't got the results i desire, because as you see in my code i want a URL with a city code and i will just change the code and that wasn't supported in the Google search generated websites – Muhammed Refaat May 16 '13 at 11:18
1

Here's a list of Weather APIs that are available via the Temboo Java SDK:

https://temboo.com/library/keyword/weather/

Cormac Driver
  • 2,511
  • 1
  • 12
  • 10
1

You can use YQL (yahoo query language) to find the WOEID by city name like

var lclqry = escape('select * from geo.places where text="OKLAHOMA CITY"') var lclurl = "http://query.yahooapis.com/v1/public/yql?q=" + lclqry + "&format=json&callback=?";

Sai
  • 11
  • 1
1

I know this is an old question, but i found it and as Sai suggested i have written code in java that send YQL query and retrieve WOEID number. Than it uses it to get weather from yahoo-weather-java-api. It needs gson dependecy which you can get by adding dependency to maven. I hope this will help someone.

EDIT

If there is more than one WOEID number for given town name, than getWeather returns weather for town with first WOEID returned.

CODE

Weather.java:

import com.github.fedy2.weather.YahooWeatherService;
import com.github.fedy2.weather.data.Channel;
import com.github.fedy2.weather.data.unit.DegreeUnit;

import com.google.gson.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import javax.xml.bind.JAXBException;

/**
 *
 * @author robert
 */
public class Weather
{
    public Channel getWeather(String townName) throws CantFindWeatherException
    {
        try
        {
            String baseUrl = "http://query.yahooapis.com/v1/public/yql?q=";
            String query = 
                    "select woeid from geo.places where text=\"" + 
                    townName + "\"";
            String fullUrlStr = baseUrl + URLEncoder.encode(query, "UTF-8") + 
                    "&format=json";

            URL fullUrl = new URL(fullUrlStr);

            ResultObject resultObject = null;
            ResultArray resultArray = null;

            try (InputStream is = fullUrl.openStream(); 
                    InputStreamReader isr = new InputStreamReader(is); 
                    BufferedReader br = new BufferedReader(isr))
            {
                String result = "";
                String read;
                while ((read = br.readLine()) != null)
                {
                    result += read;
                }

                Gson gson = new Gson();
                try
                {
                    resultObject = gson.fromJson(result, ResultObject.class);
                }
                catch (com.google.gson.JsonSyntaxException ex)
                {
                    resultArray = gson.fromJson(result, ResultArray.class);
                }
            }

            Integer woeid = null;
            if (resultObject != null)
            {
                if (resultObject.query.results != null)
                {
                    woeid = resultObject.query.results.place.woeid;
                }
            }
            else if (resultArray != null)
            {
                woeid = resultArray.query.results.place[0].woeid;
            }

            if (woeid != null)
            {
                YahooWeatherService service = new YahooWeatherService();
                Channel channel = service.getForecast(woeid.toString(), 
                        DegreeUnit.CELSIUS);
                return channel;
            }
            else
            {
                throw new CantFindWeatherException();
            }
        }
        catch (IOException | JsonSyntaxException | JAXBException ex)
        {
            throw new CantFindWeatherException(ex);
        }
    }

    private static class ResultObject
    {
        public QueryObject query;
    }

    private static class ResultArray
    {
        public QueryArray query;
    }

    private static class QueryObject
    {
        public int count;
        public String created;
        public String lang;
        public ResultsObject results;
    }

    private static class QueryArray
    {
        public int count;
        public String created;
        public String lang;
        public ResultsArray results;
    }

    private static class ResultsObject
    {
        public Place place;
    }

    private static class ResultsArray
    {
        public Place[] place;
    }

    private static class Place
    {
        public int woeid;
    }
}

CantFindWeatherException.java:

/**
 *
 * @author robert
 */
public class CantFindWeatherException extends Exception
{
    public CantFindWeatherException()
    {
    }

    public CantFindWeatherException(String message)
    {
        super(message);
    }

    public CantFindWeatherException(String message, Throwable cause)
    {
        super(message, cause);
    }

    public CantFindWeatherException(Throwable cause)
    {
        super(cause);
    }
}
bercik
  • 816
  • 1
  • 9
  • 18
0

As for the first question, I've build a website using forecast.io. It's pretty good. Good API and 1000 free calls/day. It uses latitute/longitude to find the weather of a place.

As for the second question, I would resolve what the user puts in with the Google Geocoding Api. So when they search for "New York", you check if you already have the relevant coordinates in your database, otherwise, you do an API call to Google Geocoding.

acriel
  • 167
  • 1
  • 14