1

我之前使用“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() 解组。document 中的数据与 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;
}

我需要“中间”文档来进行类型识别/以获得解组的第二个参数。

那么如何将 unmarshal 方法与 Node/Document 一起使用,其结果与使用 inputstream 的结果相同?

为瑞克编辑

我正在从这里解组 xml 数据xsds 在这个 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(不使用文档),代码就可以工作。

4

2 回答 2

4

好的,我在这里问了同样的问题,答案是:

简单添加

docBuilderFactory.setNamespaceAware(true);
于 2013-04-17T15:15:29.443 回答
3

The following code works for me with a simple test model and gives the same result in all three cases:

    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());

If you provided a systemId in the Source use-case, then you should use the same systemId on the InputSource you create:

inputSource.setSystemId(sameIdAsYouUsedForSource);

If you are still having problems could you post the XML that you are trying to unmarshal? Also if your JAXB objects were generated from an XML Schema that could provide useful information as well.

Hope this helps,

Rick

于 2013-04-16T17:20:04.840 回答