增量编译
现在我将添加一个在示例location_add.xsd中声明的新全局元素Latlong,然后对locationXB.jar)中的Bean应用Weather元素(在示例工件location_modify.xsd中声明)已修改的定义。
列表4:摘自location_modify.xsd显示已修改的Weather元素定义,并添加两个本地元素FeelsLike和Winds的过程。
..
<xsd:element name="Weather">
<xsd:complexType>
<xsd:sequence>
...
<xsd:element name="FeelsLike"
type="xsd:float"/>
...
<xsd:element name="Visibility"
type="xsd:float"/>
...
</xsd:complexType>
</xsd:element>
列表5中的摘要显示将包含XMLBeans的JAR文件的路径添加到系统属性classpath,以便上下文类型加载器可以从该JAR文件中加载已编译的模式定义,然后通过调用XmlBeans.typeLoaderUnion()方法,将这些已编译的模式定义与从XmlBeans.getBuiltinTypeSystem()返回的预编译内置模式类型结合起来。.结合的模式定义被分配到变量stl,调用compileXMLBeans()方法时使用该变量来根据模式工件更新XMLBeans。
列表5:摘自IncrementalCompilation.java
class IncrementalCompilation{
...
public static void main(String args[]) {
...
flrObj.extractJarFile(
args[oldJARFileArgPosition],
args[outputFolderPathPosition] );
flrObj.prependToClassPath(
args[outputFolderPathPosition]);
SchemaTypeLoader stl =
XmlBeans.typeLoaderUnion(
new SchemaTypeLoader[]
{ XmlBeans.getContextTypeLoader(),
XmlBeans.getBuiltinTypeSystem() });
...
for (int i =updatedXSDFileArgPosition,
j=0; j < updatedXSDDefinitionsSize;
i++,j++ ) {
updatedXSDObj[j] =
XmlObject.Factory.parse(
new File(args[i]),options);
}
augSTSObj = XmlBeans.compileXmlBeans(null,
null,updatedXSDObj , null,
stl, flrObj, options);
}
flrObj.compileJavaFiles();
flrObj.makeJarFile(args[newJARFileArgPosition]);
...
}
IncrementalCompilation.java需要输出文件夹的位置信息,将在该文件夹中创建XSB和Java文件,创建时使用打包更新Bean的FilerImpl.java JAR文件、现有Bean的JAR文件、按增量编译中应用的顺序排列的模式工件。下面是一个通过命令行调用IncrementalCompilation.java的示例,其中先编译location_add.xsd中声明的模式定义,然后是location_modify.xsd中声明的模式定义,更新outputDIR\locationXB.jar中的Bean,然后更新
outputDIR\locationXB_IncrementalCompilation.jar中打包的Bean:
java -classpath %CLASSPATH%;.\outputDIR\locationXB.jar;
IncrementalCompilation outputDIR
outputDIR\locationXB_IncrementalCompilation.jar
outputDIR\locationXB.jar location_add.xsd location_modify.xsd
通过成功解析weather或latlong XML实例文档,可以验证IncrementalCompilation.java创建的JAR文件,如示例下载中的WeatherUnmarshal.java和LatlongUnmarshal.java所示。该示例还包含UpdateUsingXSD.java,用于说明应用于源XML模式的增量编译。UpdateUsingXSD.java, compileXMLBeans()先被调用来编译源模式文件,然后用于对包含已修改模式定义的工件进行增量编译。
XML模式验证
使用scomp或Ant任务,或者使用compileXsd()和compileXmlBeans()方法调用进行编译时,XMLBeans会验证模式文档。但是,当使用编程方式编译模式时,XMLBeans API会对验证进行更多控制。通过对传递给compileXmlBeans()或重载compileXsd()方法的XMLOptions实例调用setCompileNoValidation(),可以关闭模式验证。
如果模式无效,则XMLBeans抛出XmlException异常。在实际生活中,生产系统应用程序应该提供友好的错误消息来提供错误详细信息并指示用户如何处理,因此XmlOptions类允许应用程序指定一个Collection实例来捕获并存储以XmlError对象形式返回的验证错误。 XmlError实例表示XML文档中特定位置的错误,它带有错误详细信息,如出错位置的行号和列号、简短说明和错误的严重性等等。XmlOptions 类为验证错误提供下列帮助方法:
setErrorListener (Collection)-设置一个Collection实例来捕获并存储验证期间发生的错误
setLoadLineNumbers()-从模式或XML文档创建XmlObject实例期间为开始标记标上行号;之后可以用于在XmlError实例出错的位置设置行号。
setLoadLineNumbers(String tag)-从模式或XML文档创建XmlObject实例期间为开始和结束标记(取决于tag参数的值)标上行号
现在已经熟悉了验证和错误处理API,在解析无效示例模式location_invalid.xsd的过程中我们将使用它们。我将展示如何在运行中处理验证错误并生成自定义错误消息。列表7 显示了如何捕获模式编译过程中抛出的XmlException异常,然后将验证错误集合传递到CustomErrorHandlingUtil 类,供自定义错误处理和报告使用。
列表7:摘自CustomErrorSample.java
class CustomErrorSample{
public static void main(String args[]) {
Collection errorList = new ArrayList();
XmlOptions parseOptionsObj = new XmlOptions();
parseOptionsObj.setLoadLineNumbers();
parseOptionsObj.setLoadLineNumbers(
XmlOptions.LOAD_LINE_NUMBERS_END_ELEMENT);
XmlOptions loadOptionsObj = new XmlOptions();
loadOptionsObj.setErrorListener(errorList);
try {
XmlObject[] schemaObj = new XmlObject[]
{XmlObject.Factory.parse(
new File(args[0]),parseOptionsObj)};
SchemaTypeLoader schemaTypeObj =
XmlBeans.loadXsd(schemaObj,
loadOptionsObj);
}catch (XmlException xme) {
CustomErrorHandlingUtil eUtilObj =
new CustomErrorHandlingUtil();
eUtilObj.handleXMLException(xme);
Collection userErrors =
(Collection)loadOptionsObj.get(
XmlOptions.ERROR_LISTENER);
eUtilObj.handleErrorCollection(
userErrors);
}
....
}
为了便于说明,在以上代码中使用了两个不同的XmlOptions实例;也可以只使用一个XmlOptions实例执行组合工作。从模式文档创建XmlObjects期间使用了parseOptionsObj。loadOptionsObj用于设置错误侦听器,以在模式编译期间保存验证错误。如果调用XmlObject.Factory.parse()期间没有传递parseOptionsObj,则验证错误的行号和列号将被设置为-1。
XML文档验证
默认情况下,解析期间或更新XMLBeans实例时XMLBeans不执行完整的XML实例文档验证。但是,应用程序可以调用XMLObject中一个重载的validate()方法强制执行验证:
boolean validate()-如果调用此方法的XMLObject实例符合相应的模式定义,则返回true
boolean validate(XmlOptions)-使用XmlOptions实例验证,如果调用此方法的XmlOptions实例符合相应的模式定义,则返回true
XmlOptions类提供以下两个方法在执行validate(XmlOptions)方法期间控制验证:
setValidateTreatLaxAsSkip()-跳过匹配定义的元素的验证,并将contentModel设置为lax
setValidateOnSet()-对每一个只表示简单类型的XMLBeans的getter和setter方法都将验证值。如果出现无效值,则抛出异常。请注意,此方法不能使用错误侦听器,而且此方法不验证使用XmlCursor做出的更改
举例来说,假设对全局元素Weather的Bean实例调用validate()方法。验证的范围将是整个Weather元素,包括其子元素。但是,如果对某一个局部元素(如Temperature)的Bean实例调用validate()方法,那么仅验证表示Temperature元素的实例Bean。列表8显示了如何验证整个XML实例文档并捕获验证错误以用于报告。
列表8:摘自WeatherUnmarshal.java
public class WeatherUnmarshal {
public static void main(String args[]) {
ArrayList errorList = new ArrayList();
...
optionsObj.setErrorListener(errorList);
try {
...
WeatherDocument weatherDoc =
WeatherDocument.Factory.parse(
inputXMLFile,optionsObj);
if (weatherDoc.validate(optionsObj)) {
....
} else {
// Invalid xml document.
...
customErrorHandlingUtil eUtilObj =
new customErrorHandlingUtil();
eUtilObj.handleErrorCollection(errorList);
}
}
}
如果XML实例文档无效,则使用帮助类customErrorHandlingUtil调用自定义错误处理。
现在我将添加一个在示例location_add.xsd中声明的新全局元素Latlong,然后对locationXB.jar)中的Bean应用Weather元素(在示例工件location_modify.xsd中声明)已修改的定义。
列表4:摘自location_modify.xsd显示已修改的Weather元素定义,并添加两个本地元素FeelsLike和Winds的过程。
..
<xsd:element name="Weather">
<xsd:complexType>
<xsd:sequence>
...
<xsd:element name="FeelsLike"
type="xsd:float"/>
...
<xsd:element name="Visibility"
type="xsd:float"/>
...
</xsd:complexType>
</xsd:element>
列表5中的摘要显示将包含XMLBeans的JAR文件的路径添加到系统属性classpath,以便上下文类型加载器可以从该JAR文件中加载已编译的模式定义,然后通过调用XmlBeans.typeLoaderUnion()方法,将这些已编译的模式定义与从XmlBeans.getBuiltinTypeSystem()返回的预编译内置模式类型结合起来。.结合的模式定义被分配到变量stl,调用compileXMLBeans()方法时使用该变量来根据模式工件更新XMLBeans。
列表5:摘自IncrementalCompilation.java
class IncrementalCompilation{
...
public static void main(String args[]) {
...
flrObj.extractJarFile(
args[oldJARFileArgPosition],
args[outputFolderPathPosition] );
flrObj.prependToClassPath(
args[outputFolderPathPosition]);
SchemaTypeLoader stl =
XmlBeans.typeLoaderUnion(
new SchemaTypeLoader[]
{ XmlBeans.getContextTypeLoader(),
XmlBeans.getBuiltinTypeSystem() });
...
for (int i =updatedXSDFileArgPosition,
j=0; j < updatedXSDDefinitionsSize;
i++,j++ ) {
updatedXSDObj[j] =
XmlObject.Factory.parse(
new File(args[i]),options);
}
augSTSObj = XmlBeans.compileXmlBeans(null,
null,updatedXSDObj , null,
stl, flrObj, options);
}
flrObj.compileJavaFiles();
flrObj.makeJarFile(args[newJARFileArgPosition]);
...
}
IncrementalCompilation.java需要输出文件夹的位置信息,将在该文件夹中创建XSB和Java文件,创建时使用打包更新Bean的FilerImpl.java JAR文件、现有Bean的JAR文件、按增量编译中应用的顺序排列的模式工件。下面是一个通过命令行调用IncrementalCompilation.java的示例,其中先编译location_add.xsd中声明的模式定义,然后是location_modify.xsd中声明的模式定义,更新outputDIR\locationXB.jar中的Bean,然后更新
outputDIR\locationXB_IncrementalCompilation.jar中打包的Bean:
java -classpath %CLASSPATH%;.\outputDIR\locationXB.jar;
IncrementalCompilation outputDIR
outputDIR\locationXB_IncrementalCompilation.jar
outputDIR\locationXB.jar location_add.xsd location_modify.xsd
通过成功解析weather或latlong XML实例文档,可以验证IncrementalCompilation.java创建的JAR文件,如示例下载中的WeatherUnmarshal.java和LatlongUnmarshal.java所示。该示例还包含UpdateUsingXSD.java,用于说明应用于源XML模式的增量编译。UpdateUsingXSD.java, compileXMLBeans()先被调用来编译源模式文件,然后用于对包含已修改模式定义的工件进行增量编译。
XML模式验证
使用scomp或Ant任务,或者使用compileXsd()和compileXmlBeans()方法调用进行编译时,XMLBeans会验证模式文档。但是,当使用编程方式编译模式时,XMLBeans API会对验证进行更多控制。通过对传递给compileXmlBeans()或重载compileXsd()方法的XMLOptions实例调用setCompileNoValidation(),可以关闭模式验证。
如果模式无效,则XMLBeans抛出XmlException异常。在实际生活中,生产系统应用程序应该提供友好的错误消息来提供错误详细信息并指示用户如何处理,因此XmlOptions类允许应用程序指定一个Collection实例来捕获并存储以XmlError对象形式返回的验证错误。 XmlError实例表示XML文档中特定位置的错误,它带有错误详细信息,如出错位置的行号和列号、简短说明和错误的严重性等等。XmlOptions 类为验证错误提供下列帮助方法:
setErrorListener (Collection)-设置一个Collection实例来捕获并存储验证期间发生的错误
setLoadLineNumbers()-从模式或XML文档创建XmlObject实例期间为开始标记标上行号;之后可以用于在XmlError实例出错的位置设置行号。
setLoadLineNumbers(String tag)-从模式或XML文档创建XmlObject实例期间为开始和结束标记(取决于tag参数的值)标上行号
现在已经熟悉了验证和错误处理API,在解析无效示例模式location_invalid.xsd的过程中我们将使用它们。我将展示如何在运行中处理验证错误并生成自定义错误消息。列表7 显示了如何捕获模式编译过程中抛出的XmlException异常,然后将验证错误集合传递到CustomErrorHandlingUtil 类,供自定义错误处理和报告使用。
列表7:摘自CustomErrorSample.java
class CustomErrorSample{
public static void main(String args[]) {
Collection errorList = new ArrayList();
XmlOptions parseOptionsObj = new XmlOptions();
parseOptionsObj.setLoadLineNumbers();
parseOptionsObj.setLoadLineNumbers(
XmlOptions.LOAD_LINE_NUMBERS_END_ELEMENT);
XmlOptions loadOptionsObj = new XmlOptions();
loadOptionsObj.setErrorListener(errorList);
try {
XmlObject[] schemaObj = new XmlObject[]
{XmlObject.Factory.parse(
new File(args[0]),parseOptionsObj)};
SchemaTypeLoader schemaTypeObj =
XmlBeans.loadXsd(schemaObj,
loadOptionsObj);
}catch (XmlException xme) {
CustomErrorHandlingUtil eUtilObj =
new CustomErrorHandlingUtil();
eUtilObj.handleXMLException(xme);
Collection userErrors =
(Collection)loadOptionsObj.get(
XmlOptions.ERROR_LISTENER);
eUtilObj.handleErrorCollection(
userErrors);
}
....
}
为了便于说明,在以上代码中使用了两个不同的XmlOptions实例;也可以只使用一个XmlOptions实例执行组合工作。从模式文档创建XmlObjects期间使用了parseOptionsObj。loadOptionsObj用于设置错误侦听器,以在模式编译期间保存验证错误。如果调用XmlObject.Factory.parse()期间没有传递parseOptionsObj,则验证错误的行号和列号将被设置为-1。
XML文档验证
默认情况下,解析期间或更新XMLBeans实例时XMLBeans不执行完整的XML实例文档验证。但是,应用程序可以调用XMLObject中一个重载的validate()方法强制执行验证:
boolean validate()-如果调用此方法的XMLObject实例符合相应的模式定义,则返回true
boolean validate(XmlOptions)-使用XmlOptions实例验证,如果调用此方法的XmlOptions实例符合相应的模式定义,则返回true
XmlOptions类提供以下两个方法在执行validate(XmlOptions)方法期间控制验证:
setValidateTreatLaxAsSkip()-跳过匹配定义的元素的验证,并将contentModel设置为lax
setValidateOnSet()-对每一个只表示简单类型的XMLBeans的getter和setter方法都将验证值。如果出现无效值,则抛出异常。请注意,此方法不能使用错误侦听器,而且此方法不验证使用XmlCursor做出的更改
举例来说,假设对全局元素Weather的Bean实例调用validate()方法。验证的范围将是整个Weather元素,包括其子元素。但是,如果对某一个局部元素(如Temperature)的Bean实例调用validate()方法,那么仅验证表示Temperature元素的实例Bean。列表8显示了如何验证整个XML实例文档并捕获验证错误以用于报告。
列表8:摘自WeatherUnmarshal.java
public class WeatherUnmarshal {
public static void main(String args[]) {
ArrayList errorList = new ArrayList();
...
optionsObj.setErrorListener(errorList);
try {
...
WeatherDocument weatherDoc =
WeatherDocument.Factory.parse(
inputXMLFile,optionsObj);
if (weatherDoc.validate(optionsObj)) {
....
} else {
// Invalid xml document.
...
customErrorHandlingUtil eUtilObj =
new customErrorHandlingUtil();
eUtilObj.handleErrorCollection(errorList);
}
}
}
如果XML实例文档无效,则使用帮助类customErrorHandlingUtil调用自定义错误处理。