JAXB 编组到 XML - 当模式验证失败时有没有办法处理它?
JAXB marshalling to XML - Is there a way to handle it when Schema validation fails?
我使用 JAXB
是为了 marshall/unmarshall 一些对象到 XML 文件,用于我想要实现的小型服务。现在,我的 XML 架构(.xsd 文件)包含一些 unique
约束:
<!--....-->
<xs:unique name="uniqueValueID">
<xs:selector xpath="entry/value"/>
<xs:field xpath="id"/>
</xs:unique>
<!--....-->
我已将我的 XML 模式加载到我的编组器对象中:
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....
}
当模式有效时,目标文件会正常更新,但当验证失败时,文件会被清空或数据不完整。
我猜测问题是编组器打开了一个文件流,但是当验证失败时,它没有正确处理这种情况。有没有办法正确处理这个问题,以便在验证失败时,不对 XML 文件应用写入操作?
JAX-B 编组器将写入各种 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);
}
}
请注意,在此示例中,如果编组过程失败,程序将永远不会创建输出文件,它只会丢弃缓冲区字符串。
对于一个稍微更优雅但风险更高的解决方案,缓冲写入器 (java.io.BufferedWriter),它允许创建它的调用者设置缓冲区大小。如果缓冲区大小超过文档的大小,程序可能不会向文件写入任何内容,除非程序在流上调用 close 或 flush。
我使用 JAXB
是为了 marshall/unmarshall 一些对象到 XML 文件,用于我想要实现的小型服务。现在,我的 XML 架构(.xsd 文件)包含一些 unique
约束:
<!--....-->
<xs:unique name="uniqueValueID">
<xs:selector xpath="entry/value"/>
<xs:field xpath="id"/>
</xs:unique>
<!--....-->
我已将我的 XML 模式加载到我的编组器对象中:
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....
}
当模式有效时,目标文件会正常更新,但当验证失败时,文件会被清空或数据不完整。
我猜测问题是编组器打开了一个文件流,但是当验证失败时,它没有正确处理这种情况。有没有办法正确处理这个问题,以便在验证失败时,不对 XML 文件应用写入操作?
JAX-B 编组器将写入各种 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);
}
}
请注意,在此示例中,如果编组过程失败,程序将永远不会创建输出文件,它只会丢弃缓冲区字符串。
对于一个稍微更优雅但风险更高的解决方案,缓冲写入器 (java.io.BufferedWriter),它允许创建它的调用者设置缓冲区大小。如果缓冲区大小超过文档的大小,程序可能不会向文件写入任何内容,除非程序在流上调用 close 或 flush。