我之前使用此方法从“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),代码就可以工作。
答案 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)