JAXB编组为XML-当模式验证失败时,是否可以处理它?

Nic*_*kis 3 java xml xsd jaxb marshalling

JAXB为了将一些对象编组/解组到XML文件中以用于我要实现的小型服务。现在,我的XML模式(.xsd文件)包括一些unique约束:

<!--....-->
<xs:unique name="uniqueValueID">
    <xs:selector xpath="entry/value"/>
    <xs:field xpath="id"/>
</xs:unique>
<!--....-->
Run Code Online (Sandbox Code Playgroud)

我已经将XML模式加载到marshaller对象中:

try {
//....
//Set schema onto the marshaller object
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
Schema schema = sf.newSchema(new File(xsdFileName)); 
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.setSchema(schema);

//Apply marshalling here
jaxbMarshaller.marshal(myObjectToMarshall, new File(xmlFileNName));
} catch (JAXBException | SAXException ex) {
   //Exception handling code here....
}
Run Code Online (Sandbox Code Playgroud)

架构有效时,将正常更新目标文件,但验证失败时,将清空文件或包含不完整的数据。

我猜测问题是封送程序打开了文件流,但是当验证失败时,它无法正确处理这种情况。有没有一种方法可以正确处理此问题,以便在验证失败时不对XML文件进行任何写入操作?

小智 5

JAX-B Marshaller将写入各种Java™输出接口。如果我想确定不会将任何字节写入到文件或其他固定实体中而导致编组失败,那么我将使用字符串缓冲区包含编组过程的结果,然后编写包含在缓冲区中的编组XML文档,如下所示:

     try
     {
        StringWriter output = new StringWriter ();
        JAXBContext jc = JAXBContext.newInstance (packageId);
        FileWriter savedAs;

        // Marshal the XML data to a string buffer here
        Marshaller marshalList = jc.createMarshaller ();
        marshalList.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshalList.marshal (toUpdate, output);

        // append the xml to the file to update here.
        savedAs = new FileWriter (new File (xmlFileName), true);
        savedAs.write (output.toString);
        savedAs.close();
     }
     catch (IOException iox)
     {
        String msg = "IO error on save: " + iox.getMessage ();
        throw new LocalException (msg, 40012, "UNKNOWN", iox);
     }
     catch (JAXBException jbx)
     {
        String msg = "Error writing definitions: " + jbx.getMessage ();
        throw new LocalException (msg, 40005, "UNKNOWN", jbx);
     }
  }
Run Code Online (Sandbox Code Playgroud)

请注意,在此示例中,如果编组过程失败,该程序将永远不会创建输出文件,而只会丢弃缓冲区字符串。

对于稍微更优雅甚至风险更大的解决方案,请使用缓冲的编写器(java.io.BufferedWriter),它允许创建它的调用方设置缓冲区大小。如果缓冲区大小超过文档的大小,则该程序可能不会向该文件写入任何内容,除非该程序在流上调用close或flush。

  • 合理的想法。但是,请跳过字符串,并使用字节(写入ByteArrayOutputStream),以免在处理过程中弄糟xml编码。 (2认同)