/**
   * Assume that m_xpi.name == search_match.
   *
   * @return the parsed OneListSearchMatchImpl or null if the match didn't have a position
   */
  static OneListSearchMatchImpl parse_search_match(MC2Parser mc2p)
      throws MC2ParserException, IOException {

    /*
     * xml 2.3.0
    <!ELEMENT search_match ( name, itemid,
        location_name, lat?, lon?, category_list?,
        search_area*, detail_field* )>
    <!ATTLIST search_match search_match_type %search_match_type_t; #REQUIRED
        category_image CDATA #REQUIRED
        provider_image CDATA #REQUIRED
        brand_image CDATA #REQUIRED >

    <!ENTITY % search_match_type_t "(street|pointofinterest|misc|person|
        other)">
    */

    mc2p.nameOrError(MC2Strings.tsearch_match);

    String matchID = null;
    String matchLocation = null;
    String matchName = null;

    // lat, lon are optional but we skip matches without position
    // in the future these will be filtered out by the server.
    Position position = null;

    // <!ATTLIST search_match search_match_type %search_match_type_t; #REQUIRED
    //           category_image CDATA #REQUIRED
    //           provider_image CDATA #REQUIRED
    //           brand_image CDATA #REQUIRED
    //           additional_info_exists %bool; #REQUIRED >

    // XML spec for search_match attributes
    //   Images are without file extension and are empty if there is no such
    //   image for the search_match.
    final String brandImageName = mc2p.attribute(MC2Strings.abrand_image);
    final String categoryImageName = mc2p.attribute(MC2Strings.acategory_image);
    final String providerImageName = mc2p.attribute(MC2Strings.aprovider_image);
    final boolean additionalInfoExists =
        mc2p.attributeAsBoolean(MC2Strings.aadditional_info_exists);

    /*
    <!ELEMENT search_match ( name, itemid,
            location_name, lat?, lon?,
            category_list?,     //skipped
            search_area*,       //skipped
            detail_item? )>     //included if include_detail_fields is true
     */

    // there is at least 3 subelements
    mc2p.childrenOrError();

    // create this only if we expect info fields
    PoiDetailImpl detail = null;

    do {
      if (mc2p.nameRefEq(MC2Strings.tname)) { // FIXME: MC2Strings
        matchName = mc2p.value();
      } else if (mc2p.nameRefEq(MC2Strings.titemid)) {
        matchID = mc2p.value();
      } else if (mc2p.nameRefEq(MC2Strings.tlat)) {
        int lat = mc2p.valueAsInt();
        if (mc2p.advance() && mc2p.nameRefEq(MC2Strings.tlon)) {
          int lon = mc2p.valueAsInt();
          position = new Position(lat, lon);
        }
      } else if (mc2p.nameRefEq(MC2Strings.tlocation_name)) {
        matchLocation = mc2p.value();
      } else if (mc2p.nameRefEq(MC2Strings.tdetail_item)) {
        detail = mc2p.parseDetailItem();
      }
    } while (mc2p.advance());

    mc2p.nameOrError(MC2Strings.tsearch_match);

    if (position == null) {
      return null;
    } else if (matchID == null || matchLocation == null || matchName == null) {
      throw new MC2ParserException("Invalid data for search_match");
    } else {
      return new OneListSearchMatchImpl(
          matchID,
          matchLocation,
          matchName,
          position,
          brandImageName,
          categoryImageName,
          providerImageName,
          detail,
          additionalInfoExists);
    }
  }