JAXB XML Динамическое демаршаллинг - PullRequest
1 голос
/ 18 октября 2019

Итак, у меня есть пара XML, которые я пытаюсь разобрать.

Один XML может выглядеть так:

<TABLE>
    <RECORDS>
        <RECORD>
            <DOC_ID>some value</DOC_ID>
            <ENTITY_ID>some value</ENTITY_ID>
            ...more entries
        </RECORD>
        <RECORD>
            <DOC_ID>some value</DOC_ID>
            <ENTITY_ID>some value</ENTITY_ID>
            ...more entries
        </RECORD>
    </RECORDS>
</TABLE>

Другой XML также может выглядеть так:

<TABLE>
    <RECORDS>
        <RECORD>
            <SUB_ID>some value</SUB_ID>
            <CASE_DOC_ID>some value</CASE_DOC_ID>
            ...more entries
        </RECORD>
        <RECORD>
            <SUB_ID>some value</SUB_ID>
            <CASE_DOC_ID>some value</CASE_DOC_ID>
            ...more entries
        </RECORD>
    </RECORDS>
</TABLE>

Каждый XML всегда имеет TABLE в качестве root и RECORDS в качестве дочернего элемента и RECORD в качестве внука, просто данные в RECORD различны.

Я не хочу ничего маршалировать, просто разбирать иполучить данные.

Внутри моего класса таблицы у меня есть

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "TABLE")
public class Table {

    @XmlJavaTypeAdapter(MapAdapter.class)
    private Map<String, String> RECORDS;

    public Map<String, String> getMap() {
        return RECORDS;
    }

    public void setMap(Map<String, String> record) {
        this.RECORDS = record;
    }

}

Я взял MapAdapter по этой ссылке: JAXB Marshal и Unmarshal Map to / from значение

Моя проблема заключается в следующем: я хотел бы иметь возможность получить каждое имя тега в записи (DOC_ID / SUB_ID или любое другое в XML) и каждыйего значения в виде строк, когда я передаю XML, но я не уверен, как это сделать.

Буду признателен за любую помощь, чтобы указать мне правильное направление.

РЕДАКТИРОВАТЬ:

2 новых вопроса! Я понял, что мне, вероятно, понадобится список Карт для всех записей.

  • Мне удалось получить ключи и значения последней записи, используя приведенный выше класс Table. Как мне превратить его в список Карт, чтобы я мог получить каждую запись вместо только последней?
  • Еще один вопрос - класс Table работает только в том случае, если в моем xml нет тега RECORDS. Как мне это исправить?

1 Ответ

0 голосов
/ 18 октября 2019

Вы должны иметь возможность комментировать Map с помощью MapAdapter из ссылки , которую вы указали, поэтому вам нужно создать подкласс.

@XmlJavaTypeAdapter(MapAdapter.class)
public class Record extends HashMap<String, String> {
}

Тогда вашКласс таблицы достаточно прост, хотя вам нужно пометить @XmlElementWrapper, чтобы получить дополнительный уровень XML.

@XmlRootElement(name = "TABLE")
public class Table {
    private List<Record> records = new ArrayList<>();

    @XmlElementWrapper(name = "RECORDS")
    @XmlElement(name = "RECORD")
    public List<Record> getRecords() {
        return this.records;
    }
    public void setRecords(List<Record> records) {
        this.records = records;
    }
}

При работе с JAXB и синтаксический анализ не загружает всея обнаружил, что эта информация помогает сначала написать код для генерации XML, потому что в сгенерированном XML вы можете увидеть, как отображения JAXB отличаются от того, что вы ожидали / намеревались.

Создать пример данных проще, если вы добавите несколько вспомогательных методов в вышеупомянутые классы, поэтому давайте сделаем это сначала:

@XmlJavaTypeAdapter(MapAdapter.class)
public class Record extends HashMap<String, String> {
    private static final long serialVersionUID = 1L;

    public Record addElement(String name, String value) {
        put(name, value);
        return this;
    }

    @Override
    public String toString() {
        return "Record" + super.toString();
    }
}
@XmlRootElement(name = "TABLE")
public class Table {
    private List<Record> records;

    public Table() {
        this.records = new ArrayList<>();
    }
    public Table(Record... records) {
        this.records = Arrays.asList(records);
    }

    @XmlElementWrapper(name = "RECORDS")
    @XmlElement(name = "RECORD")
    public List<Record> getRecords() {
        return this.records;
    }
    public void setRecords(List<Record> records) {
        this.records = records;
    }

    @Override
    public String toString() {
        return "Table" + this.records.toString();
    }
}

Затем мы можем легко написать тестовый код, чтобы увидеть, что онвсе работает нормально.

Создание данных для генерации в виде XML

Table table1 = new Table(
        new Record().addElement("DOC_ID", "some value")
                    .addElement("ENTITY_ID", "some value"),
        new Record().addElement("SUB_ID", "some value")
                    .addElement("CASE_DOC_ID", "some value")
);
System.out.println(table1);
Table[Record{DOC_ID=some value, ENTITY_ID=some value}, Record{SUB_ID=some value, CASE_DOC_ID=some value}]

Создание XML

String xml;
try (StringWriter out = new StringWriter()) {
    JAXBContext jaxbContext = JAXBContext.newInstance(Table.class);
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(table1, out);
    xml = out.toString();
}
System.out.println(xml);
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TABLE>
    <RECORDS>
        <RECORD>
            <DOC_ID>some value</DOC_ID>
            <ENTITY_ID>some value</ENTITY_ID>
        </RECORD>
        <RECORD>
            <SUB_ID>some value</SUB_ID>
            <CASE_DOC_ID>some value</CASE_DOC_ID>
        </RECORD>
    </RECORDS>
</TABLE>

Мы можем подтвердить, что отображения JAXB генерируют формат XML, который мы намереваемся проанализировать.

Parse XML

Table table2;
{
    JAXBContext jaxbContext = JAXBContext.newInstance(Table.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
    table2 = (Table) unmarshaller.unmarshal(new StringReader(xml));
}
System.out.println(table2);
Table[{DOC_ID=some value, ENTITY_ID=some value}, {SUB_ID=some value, CASE_DOC_ID=some value}]

Как видите, проанализированные данные имеют все значения и соответствуют исходным данным.

...