Объединение новых элементов в XML-файл и группировка их по годам - PullRequest
0 голосов
/ 28 января 2019

Моя проблема в том, что я хочу сохранить мои Expenditure объекты по их Data в XML-файле, но для каждого Expenditure экземпляра создается новый элемент Year, и он выглядит так:

<Expenditures xmlns="testing">
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2017">
    <Expenditure>
      <date>03-01-2017</date>
      <money>USD 2</money>
      <description>parking ticket</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2019">
    <Expenditure>
      <date>09-01-2019</date>
      <money>PLN 1.5</money>
      <description>Batonik czekoladowy</description>
      <type>FOOD</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2019">
    <Expenditure>
      <date>09-01-2019</date>
      <money>USD 1.5</money>
      <description>guma balonowa</description>
      <type>FOOD</type>
    </Expenditure>
  </year>
</Expenditures>

Мой XML должен выглядеть так:

<Expenditures xmlns="testing">
  <year xmlns="" y="2014">
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
        <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
        <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
    <Expenditure>
      <date>01-01-2014</date>
      <money>EUR 1</money>
      <description>bilet autobusowy</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2017">
    <Expenditure>
      <date>03-01-2017</date>
      <money>USD 2</money>
      <description>parking ticket</description>
      <type>TRANSPORT</type>
    </Expenditure>
  </year>
  <year xmlns="" y="2019">
    <Expenditure>
      <date>09-01-2019</date>
      <money>PLN 1.5</money>
      <description>Batonik czekoladowy</description>
      <type>FOOD</type>
    </Expenditure>
    <Expenditure>
      <date>09-01-2019</date>
      <money>USD 1.5</money>
      <description>guma balonowa</description>
      <type>FOOD</type>
    </Expenditure>
  </year>
</Expenditures>

Это мой код:

    public static void mergeToXMLTesting() throws Exception {
        User user = User.mock();
        Document doc = new Document();
        doc.setRootElement(new Element("Expenditures", Namespace.getNamespace("testing")));
        InputStream in = Main.class.getResourceAsStream(System.getProperty("user.dir") + "/testxml2.xml");

        SAXBuilder builder = new SAXBuilder();
        File xmlFile = new File(System.getProperty("user.dir") + "/testxml2.xml");
        Document document = (Document) builder.build(xmlFile);
        Element rootNode = document.getRootElement();

        for (Expenditure e : user.getExpenditures()) {
            int year = e.getDate().getYear();
            String query = "//year[@y='" + year + "']";
            XPathExpression<Element> xpe = XPathFactory.instance().compile(query, Filters.element());
            Element thisYear = null;
            if (!xpe.evaluate(document).isEmpty()) {
                thisYear = xpe.evaluate(document).get(0);

                System.out.println("found year " + year);

                Element expenditure = new Element("Expenditure");
                expenditure.addContent(new Element("date")
                        .setText(Utils.getFormattedDateTime("dd-MM-yyyy", new DateTime(e.getDate()))));
                expenditure.addContent(new Element("money").setText(e.getMonetaryAmount().toString()));
                expenditure.addContent(new Element("description").setText(e.getDescription()));
                expenditure.addContent(new Element("type").setText(e.getType().name()));
                thisYear.addContent(expenditure);
            } else {
                thisYear = new Element("year");
                thisYear.setAttribute("y", year + "");
                Element expenditure = new Element("Expenditure");
                expenditure.addContent(new Element("date")
                        .setText(Utils.getFormattedDateTime("dd-MM-yyyy", new DateTime(e.getDate()))));
                expenditure.addContent(new Element("money").setText(e.getMonetaryAmount().toString()));
                expenditure.addContent(new Element("description").setText(e.getDescription()));
                expenditure.addContent(new Element("type").setText(e.getType().name()));
                thisYear.addContent(expenditure);
                //doc.getRootElement().addContent(thisYear);
            }
            doc.getRootElement().addContent(thisYear);
        }
        XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
        xmlOutputter.output(doc, new FileOutputStream(System.getProperty("user.dir") + "/testxml2.xml"));
    }

1 Ответ

0 голосов
/ 28 января 2019

Проблема в том, что вы помещаете элемент thisYear на каждую итерацию цикла for (Expenditure e : user.getExpenditures()).

Я бы порекомендовал переписать всю эту логику немного иначе: сгруппируйте ваши расходы по годам, прежде чем выполнять их итерацию.

Map<Integer, List<Expenditure>> groups = expenditures.stream().collect(Collectors.groupingBy(e -> e.getDate().getYear()));
for (Entry<Integer, List<Expenditure>> entry : groups.entrySet()) {
    thisYear = new Element("year");
    thisYear.setAttribute("y", year + "");
    entry.getValues().forEach( e -> {
        Element expenditure = new Element("Expenditure");
        expenditure.addContent(new Element("date")
                .setText(Utils.getFormattedDateTime("dd-MM-yyyy", new DateTime(e.getDate()))));
        expenditure.addContent(new Element("money").setText(e.getMonetaryAmount().toString()));
        expenditure.addContent(new Element("description").setText(e.getDescription()));
        expenditure.addContent(new Element("type").setText(e.getType().name()));
        thisYear.addContent(expenditure);
    });
    doc.getRootElement().addContent(thisYear);

}

Извините, если есть какие-либо ошибки компиляции,У меня нет всего контекста кода.

...