Демаршалировать xml с использованием Document вместо StreamSource

Ранее я демонтировал свои документы с помощью этого метода из "javax.xml.bind.Unmarshaller" (я использую Moxy в качестве поставщика jaxb):

<Object> JAXBElement<Object> javax.xml.bind.Unmarshaller.unmarshal(Source source, Class<Object> declaredType) throws JAXBException

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

<?> JAXBElement<?> javax.xml.bind.Unmarshaller.unmarshal(Node node, Class<?> declaredType) throws JAXBException

Проблема в том, что я получаю немаршалированное исключение:

    Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: org.xml.sax.SAXParseExceptionpublicId: ; systemId: ; lineNumber: 0; columnNumber: 0; cvc-elt.1: Cannot find the declaration of element 'invoice:request'.]

Я пробовал демаршалировать с помощью Document и Document.getDocumentElement (). Данные в документе такие же, как и в InputStream. Документ создается таким образом:

    protected static Document extractDocument(InputStream sourceData) {
    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    Document doc;
    try {
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
        doc = docBuilder.parse(new InputSource(sourceData));
    } catch (Exception e) {
        throw new IllegalArgumentException("Problem on reading xml, cause: ", e);
    }
    return doc;
}

Мне нужен «промежуточный» документ для распознавания типа / для получения второго аргумента для демаршалирования.

Итак, как использовать метод демаршалирования с Node / Document, чтобы результат был таким же, как при использовании с входным потоком?

Редактировать для Рика

Я неупорядочиваю XML-данные с здесь. в этом zip и примерами являются здесь.

Я написал простой тест (провайдер jaxb - moxy, он также использовался для генерации классов привязки):

    @Test
public void test() throws Exception {
    Unmarshaller um;
    JAXBContext jaxbContext = JAXBContext
            .newInstance("....generatedClasses.invoice.general430.request");
    um = jaxbContext.createUnmarshaller();

    InputStream xmlIs = SingleTests.class.getResourceAsStream("/430_requests/dentist_ersred_TG_430.xml");

    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = sf.newSchema(this.getClass().getResource("/xsd/" + "generalInvoiceRequest_430.xsd"));
    // start
    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    Document doc;
    try {
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
        doc = docBuilder.parse(new InputSource(xmlIs));
    } catch (Exception e) {
        throw new Exception("Problem on recognizing invoice type of given xml, cause: ", e);
    }
    // end
    um.setSchema(schema);
    um.unmarshal(doc, ....generatedClasses.invoice.general430.request.RequestType.class);

}

Это не работает с описанной выше ошибкой. Но как только удален «начальный конечный блок» и демаршалирует поток xmlIs напрямую (без использования документа), код работает.


person dermoritz    schedule 16.04.2013    source источник


Ответы (2)


Хорошо, я задал тот же вопрос здесь, ответ:

простое добавление

docBuilderFactory.setNamespaceAware(true);
person dermoritz    schedule 17.04.2013

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

    JAXBContext ctx = JAXBContext.newInstance(new Class[] { TestObject.class }, null);

    Source source = new StreamSource("src/stack16038604/instance.xml");
    JAXBElement o1 = ctx.createUnmarshaller().unmarshal(source, TestObject.class);
    System.out.println(o1.getValue());

    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    InputStream inputStream2 = ClassLoader.getSystemResourceAsStream("stack16038604/instance.xml");
    Document node = builderFactory.newDocumentBuilder().parse(inputStream2);
    JAXBElement o2 = ctx.createUnmarshaller().unmarshal(node, TestObject.class);
    System.out.println(o2.getValue());

    DocumentBuilderFactory builderFactory2 = DocumentBuilderFactory.newInstance();
    InputStream inputStream3 = ClassLoader.getSystemResourceAsStream("stack16038604/instance.xml");
    InputSource inputSource = new InputSource(inputStream3);
    Document node2 = builderFactory2.newDocumentBuilder().parse(inputSource);
    JAXBElement o3 = ctx.createUnmarshaller().unmarshal(node2, TestObject.class);
    System.out.println(o3.getValue());

Если вы указали systemId в сценарии использования Source, вы должны использовать тот же systemId в InputSource, который вы создаете:

inputSource.setSystemId(sameIdAsYouUsedForSource);

Если у вас все еще есть проблемы, не могли бы вы опубликовать XML, который вы пытаетесь демаршалировать? Также, если ваши объекты JAXB были сгенерированы из схемы XML, которая также может предоставить полезную информацию.

Надеюсь это поможет,

Рик

person Rick Barkhouse    schedule 16.04.2013
comment
Я отредактировал свой вопрос. Я пробовал (это тоже была моя первая попытка) использовать документ напрямую, но он не работает. - person dermoritz; 17.04.2013