private TeamResult readTeamResultXml(
      final List<MatchInfo> matchCache,
      final List<TeamInfo> teamCache,
      final List<Category> categories,
      final Element resultElm)
      throws Exception {
    /*  example team result XML file content
    <result matchNumber="1" teamNumber="1" cat1="-1" cat2="-1" cat3="-1" ... >
        Specific notes about this team and this match
    </result>
    */

    // Process <result> XML element
    int theMatchNumber = resultElm.getAttribute("matchNumber").getIntValue();
    MatchInfo match =
        matchCache.stream().filter(m -> m.getMatchNumber() == theMatchNumber).findFirst().get();

    int theTeamNumber = resultElm.getAttribute("teamNumber").getIntValue();
    TeamInfo team =
        teamCache.stream().filter(t -> t.getTeamNumber() == theTeamNumber).findFirst().get();

    Map<Category, Integer> scores = new HashMap<>();
    for (Category c : categories) {
      String score = resultElm.getAttributeValue(c.getName());
      if ((score != null) && (score.length() > 0)) {
        scores.put(c, Integer.valueOf(score));
      }
    }

    TeamResult tr = new TeamResult(match, team, scores);
    tr.setNotes(resultElm.getTextNormalize());

    return tr;
  }
  private Element writeCategoriesXml(final Collection<Category> categories) {
    /*  example category XML file content
    <categories>
        <category name="cat1" displayName="Category 1" valueType="java.lang.Integer" minValue="0" maxValue="10" />
        <category name="cat1" displayName="Category 1" valueType="java.lang.Integer" minValue="0" maxValue="10" />
        <category name="cat1" displayName="Category 1" valueType="java.lang.Integer" minValue="0" maxValue="10" />
    </categories>
    */
    Element rootElm = new Element("categories");

    for (Category c : categories) {
      Element categoryElm = new Element("category");
      categoryElm.setAttribute("name", c.getName());
      categoryElm.setAttribute("displayName", c.getDisplayName());
      if (c.getMinValue() != null) {
        categoryElm.setAttribute("minValue", c.getMinValue().toString());
      }
      if (c.getMaxValue() != null) {
        categoryElm.setAttribute("maxValue", c.getMaxValue().toString());
      }

      rootElm.addContent(categoryElm);
    }

    return rootElm;
  }
  private Element writeTeamResultXml(final TeamResult result) {
    /*  example team result XML file content
    <result matchNumber="1" teamNumber="1" cat1="-1" cat2="-1" cat3="-1" ... >
        Specific notes about this team and this match
    </result>
    */

    Element rootElm = new Element("result");
    rootElm.setAttribute("matchNumber", Integer.toString(result.getMatch().getMatchNumber()));
    rootElm.setAttribute("teamNumber", Integer.toString(result.getTeam().getTeamNumber()));

    for (Category c : result.getScoringCategories()) {
      rootElm.setAttribute(c.getName(), result.getScore(c).toString());
    }

    rootElm.setText(result.getNotes());
    return rootElm;
  }