void Metalink3Reader::start_element(wxString name,
                                    std::map<std::string, wxString> attrs)
{
    if(!remove_namespace(name)) return;
    switch(state_) {
        case STATE_NONE:
            if(name == wxT("metalink") && attrs["version"] == wxT("3.0")) {
                recognized_ = true;
                state_ = STATE_METALINK;
            }
        break;
        case STATE_METALINK:
            if(name == wxT("file")) {
                if(attrs.count("name") != 1) {
                    throw MetalinkLoadError("Missing 'name' attribute on file "
                                            "element.");
                }
                file_ = MetalinkFile(attrs["name"]);
                state_ = STATE_FILE;
            }
        break;
        case STATE_FILE:
            if(name == wxT("resources")) {
                state_ = STATE_RESOURCES;
            }
        break;
        case STATE_RESOURCES:
            if(name == wxT("url")) {
                source_ = MetalinkSource();
                if(attrs["type"] == wxT("bittorrent")) {
                    source_.set_torrent(true);
                }
                if(attrs.count("location") == 1) {
                    source_.set_location(attrs["location"]);
                }
                if(attrs.count("preference") == 1) {
                    source_.set_priority(attrs["preference"]);
                }
                state_ = STATE_URL;
            }
        break;
    }
    data_.clear();
}
void Metalink3Reader::start_element(wxString name,
                                    std::map<std::string, wxString> attrs)
{
    if(!remove_namespace(name)) return;
    switch(state_) {
        case STATE_NONE:
            if(name == wxT("metalink") && attrs["version"] == wxT("3.0")) {
                recognized_ = true;
                state_ = STATE_METALINK;
            }
        break;
        case STATE_METALINK:
            if(name == wxT("file")) {
                if(attrs.count("name") != 1) {
                    throw MetalinkLoadError("Missing 'name' attribute on file "
                                            "element.");
                }
                file_ = MetalinkFile(attrs["name"]);
                state_ = STATE_FILE;
            }
        break;
        case STATE_FILE:
            if(name == wxT("resources")) {
                state_ = STATE_RESOURCES;
            } else if(name == wxT("pieces")) {
                if(attrs.count("length") != 1 || attrs.count("type") != 1) {
                    throw MetalinkLoadError("Missing attribute on pieces "
                                            "element.");
                }
                file_.set_piece_hash_type(attrs["type"]);
                file_.set_piece_length(attrs["length"]);
                piece_hashes_.clear();
                state_ = STATE_PIECES;
            } else if(name == wxT("hash")) {
                if(attrs.count("type") != 1) {
                    throw MetalinkLoadError("Missing 'type' attribute on "
                                            "hash element");
                }
                hash_ = MetalinkHash(attrs["type"]);
            }
        break;
        case STATE_RESOURCES:
            if(name == wxT("url")) {
                source_ = MetalinkSource();
                if(attrs["type"] == wxT("bittorrent")) {
                    source_.set_torrent(true);
                }
                if(attrs.count("location") == 1) {
                    source_.set_location(attrs["location"]);
                }
                if(attrs.count("preference") == 1) {
                    source_.set_priority(attrs["preference"]);
                }
                state_ = STATE_URL;
            }
        break;
        case STATE_PIECES:
            if(name == wxT("hash")) {
                if(attrs.count("piece") != 1) {
                    throw MetalinkLoadError("Missing 'piece' attribute on "
                                            "hash element");
                }
                bool isnum = attrs["piece"].ToLong(&piece_);
                if(!isnum || piece_ < 0 || piece_ > 5000) {
                    throw MetalinkLoadError("Invalid piece number");
                }
            }
        break;
    }
    data_.clear();
}