使用Document而不是StreamSource解组xml

时间:2013-04-16 13:36:59

标签: java xml moxy unmarshalling

我之前使用此方法从“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;
}

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

那么如何在Node / Document中使用unmarshal方法,结果与输入流使用的结果相同?

编辑rick

我正在解冻来自here xsds的xml数据位于this zip,示例为here

我写了一个简单的测试(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(不使用Document),代码就可以工作。

2 个答案:

答案 0 :(得分:3)

以下代码适用于我,使用简单的测试模型,并在所有三种情况下得到相同的结果:

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

如果您在Source用例中提供了systemId,那么您应该在您创建的InputSource上使用相同的systemId:

inputSource.setSystemId(sameIdAsYouUsedForSource);

如果您仍然遇到问题,可以发布您要解组的XML吗?此外,如果您的JAXB对象是从XML Schema生成的,也可以提供有用的信息。

希望这有帮助,

瑞克

答案 1 :(得分:3)

好的,我问同一个问题here答案是:

简单添加

docBuilderFactory.setNamespaceAware(true);