Как сгруппировать теги XML

Я пытаюсь изменить формат xml, сгруппировав элементы. В формате ниже будут использоваться первые три элемента статьи (ID, NAME и CITY). для группировки элементов MEDIA. Это означает, что если элементы (ID, NAME и CITY) имеют ту же информацию, что и другие три элемента в другой статье, то элементы MEDIA будут сгруппированы по элементам (ID, NAME и CITY).

Например:

Вход

<Article>
    <ID>100</ID>
    <NAME>A</NAME>
    <CITY>XX</CITY>
    <MEDIA>
        <MEDIANAME>PPP</MEDIANAME>
        <MEDIACOLOR>RED></MEDIACOLOR>
    </MEDIA>
</Article>
<Article>
    <ID>100</ID>
    <NAME>A</NAME>
    <CITY>XX</CITY>
    <MEDIA>
        <MEDIANAME>PPC</MEDIANAME>
        <MEDIACOLOR>YELLOW></MEDIACOLOR>
    </MEDIA>
</Article>
<Article>
    <ID>101</ID>
    <NAME>B</NAME>
    <CITY>YY</CITY>
    <MEDIA>
        <MEDIANAME>PPX</MEDIANAME>
        <MEDIACOLOR>BLACK></MEDIACOLOR>
    </MEDIA>
</Article>
<Article>
    <ID>101</ID>
    <NAME>B</NAME>
    <CITY>YY</CITY>
    <MEDIA>
        <MEDIANAME>PPZ</MEDIANAME>
        <MEDIACOLOR>PURPLE></MEDIACOLOR>
    </MEDIA>
</Article>

Выход

<Article>
    <ID>100</ID>
    <NAME>A</NAME>
    <CITY>XX</CITY>
    <MEDIA>
        <MEDIANAME>PPP</MEDIANAME>
        <MEDIACOLOR>RED></MEDIACOLOR>
    </MEDIA>
    <MEDIA>
        <MEDIANAME>PPC</MEDIANAME>
        <MEDIACOLOR>YELLOW></MEDIACOLOR>
    </MEDIA>
</Article>
<Article>
    <ID>101</ID>
    <NAME>B</NAME>
    <CITY>YY</CITY>
    <MEDIA>
        <MEDIANAME>PPX</MEDIANAME>
        <MEDIACOLOR>BLACK></MEDIACOLOR>
    </MEDIA>
    <MEDIA>
        <MEDIANAME>PPZ</MEDIANAME>
        <MEDIACOLOR>PURPLE></MEDIACOLOR>
    </MEDIA>
</Article>

Могу ли я узнать, как добиться этого с помощью Java? Я буду получать xml только в этом формате, поэтому мне остается только изменить файл, чтобы сгруппировать элементы. Это всего лишь образец, фактический файл намного больше, чем этот, и большее количество элементов.

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

Какая часть задачи представляет для вас проблему? Вы умеете читать файлы XML? Вы знаете, как сгруппировать данные в памяти? Вы знаете, как записывать данные в XML-файл?

yole 11.03.2018 18:09

@yole, как я могу взять ссылку на первые три элемента статьи, чтобы проверить другие на предмет той же информации, и добавить свои элементы МЕДИА, если они найдут какое-либо совпадение? Да, я умею читать XML. Группа данных в этом случае не может найти никакого способа. Да, я знаю, как записывать данные в xml. :) Запись данных в xml здесь не используется (уже есть xml), во-вторых, можете ли вы сказать, читаете ли вы xml, как мы можем сделать эти группы? :)

Squeez 11.03.2018 18:15
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
719
2

Ответы 2

Вам нужно сделать несколько вещей.

  1. Вам нужно прочитать ваш XML в Java. Для этого существует библиотека JAXB. JAXB поможет вам упорядочить и демаршалировать Java в / из XML.
  2. Вам необходимо определить вашу информационную модель. Судя по всему, у вас есть класс под названием Article с 3 (строковыми) полями с именами id, name и city, которые вместе образуют уникальный идентификатор экземпляра этого класса. Затем у вас есть список объектов Media, каждый из которых состоит из имени и цвета.
  3. В вашей информационной модели вам необходимо перезаписать функции equals () и hashcode (), чтобы равенство было найдено, когда 2 экземпляра класса Article имеют одинаковые 3 идентификатора, имени и города.

Теперь используйте JAXB, чтобы прочитать XML-файл на List<Article>, который будет содержать все статьи в вашем исходном XML.

Затем создайте карту. Затем перейдите по списку и добавьте каждый элемент на карту (map.put(article,article)). Если карта уже содержит эту статью, вы берете ее и обновляете раздел мультимедиа. Например: map.get(currentArticle).getMedia.addAll(currentArticle.getMedia())

Когда вы закончите, вы можете снова преобразовать Java в XML.

NB: причина использования карты, а не набора, заключается в том, что вам нужно иметь возможность извлекать объект и изменять его, чего в наборе вы не можете.

Спасибо, что поделились, но никогда не использовал библиотеку JAXB. Хорошо, я попробую это использовать. Возможно ли, что вы могли бы поделиться каким-либо образцом кода для этого подхода?

Squeez 11.03.2018 18:25

Чтобы расширить ответ Дэвида, вам не обязательно нужен jaxb (хотя это может облегчить вашу жизнь). В вашем XML-файле отсутствует корневой узел, что приведет к возникновению исключения из-за недопустимого формата. Это должно быть похоже

<Articles>
    <Article>...</Article>
    ...
</Articles>

Используя только стандартный java7, вы можете объявить объект XPath

private final XPath xpath = XPathFactory.newInstance().newXPath();

И используйте это в методе, который считывает ваш XML-документ в объекты Java следующим образом:

String file = "/path/to/your/xml/file.xml";
FileInputStream fis = new FileInputStream(file);
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(fis);
NodeList nl = (NodeList) xpath.evaluate("/Articles/Article", doc, XPathConstants.NODESET);
List<Article> articles = new ArrayList<>();
for (int i = 0; i < nl.getLength(); i++) {
    articles.add(new Article(nl.item(i)));
}
List<Article> merged = mergeMedia(articles);

с классом Article, например

private class Article {
    private String id;
    private String name;
    private String city;
    private List<Media> media;
    // getters, setters
    public Article(Node node) throws Exception {
        this.id = (String) xpath.evaluate("ID", node, XPathConstants.STRING);
        this.name = (String) xpath.evaluate("NAME", node, XPathConstants.STRING);
        this.city = (String) xpath.evaluate("CITY", node, XPathConstants.STRING);
        this.media = new ArrayList<Media>();
        media.add(new Media((Node) xpath.evaluate("MEDIA", node, XPathConstants.NODE)));
    }
}

и аналогичный медиа-класс.

Реализуйте метод объединения объектов, как вы описали (mergeMedia(articles) в моем примере), возвращая List или какой-либо другой Collection, а затем конвертируйте его обратно в xml по мере необходимости.

Другие вопросы по теме