Как использовать javax.xml.bind для записи XML в POJO с полем xmlns? - PullRequest
0 голосов
/ 10 декабря 2018

Это пример xml-объекта, подобный тому, что я получаю из моего вызова API:

<?xml version="1.0" ?>
<sourceSets>
    <sourceSet>
        <sourceSetIdentifier>1055491</sourceSetIdentifier>
        <sourceSetData>...</sourceSetName>
    </sourceSet>
    <sourceSet>
        <sourceSetIdentifier>1055493</sourceSetIdentifier>
        <sourceSetData>...</sourceSetName>
    </sourceSet>
</sourceSets>

Здесь SourceSets.java:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "sourceSets")
public class SourceSets {
       @XmlElement(required = true)
       protected List<SourceSet> sourceSet;

       // getter, setter
}

SourceSet.java также есть и естьпроверено работает, нет проблем.

Чтобы прочитать это, я использую:

inputXML = ... // as seen above

public static void main(String[] args) {

    InputStream ins = new ByteArrayInputStream(
        inputString.getBytes(StandardCharsets.UTF_8));

    SourceSets sourceSets = null;
    try {

        JAXBContext jc = JAXBContext
                .newInstance(SourceSets.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        sourceSets = (SourceSets) unmarshaller.unmarshal(is);
    } catch (PropertyException e) {
        e.printStackTrace();
    } catch (JAXBException e) {
        e.printStackTrace();
    }

    System.out.println("Length of source sets");
    System.out.println(sourceSets.getSourceSet().size());
}

И в результате получается:

Length of source sets
2

Проблема заключается в том, что XML на самом деле поставляется спространство имен, прикрепленное к объекту sourceSets:

<sourceSets xmlns="http://source/url">

Теперь, если я попытаюсь запустить свой скрипт, я получу UnmarshallException:

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://source/url", local:"sourceSets"). Expected elements are <{}sourceSet>,<{}sourceSets>,<{}subscription>
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
    ...
    at com.package.testing.SourceManualTest.main(SourceManualTest.java:78)

Так что к SourceSets.java я добавляюопределение пространства имен для аннотации @XmlRootElement, например

@XmlRootElement(namespace = "http://source/url", name = "sourceSets")

С этим изменением UnmarshallException исчезает и снова запускается ... но теперь он не читает ни в каких объектах SourceSet:

Length of source sets
0

Как мне учесть тег xml пространства имен, но все же проанализировать xml в POJO?

1 Ответ

0 голосов
/ 10 декабря 2018

У вас есть несколько альтернатив:

  1. Определение пространства имен в файле package-info.java:
@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED,
        namespace = "http://your-namespace.org/")
package org.your_namespace;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Явно определите пространство имен во всех аннотациях элементов XML:
@XmlRootElement(name = "sourceSets", namespace = "http://your-namespace.org/")
public class SourceSets {
    @XmlElement(required = true, namespace = "http://your-namespace.org/")
    protected List<SourceSet> sourceSet;
}

Смежный вопрос: JAXB: аннотация пространства имен не наследуется во время демаршаллинга - регрессия в JDK 1.8_102?

...