IMS提供了QTI规范的XSD版本,在实现过程涉及到XML与编程对象之间的转换。从几个实现QTI规范的开源项目来看,大多使用JAVA实现。在将QTI XSD转换成JAVA类时,使用JAXB来实现,但这些使用JAXB将imsqti_v2p1.xsd转换成java类的过程中,总是报错。在一些硕士论文中关于这方面的实现多是采用XMLBean来实现,通过GOOGLE来搜索了一些这方面的资料,收获很少。下面将这个转换过程做笔记于此。
一、QTI相关XSD下载
可从官方下载完成的规范文档:http://www.imsglobal.org/question/index.html#version2.0
其中包含有XSD,但其中只包含有imsqti_v2p1.xsd。为了获取更完整的XSD文件,我从一个实现QTI的开源项目中Aqurate(http://aqurate.kingston.ac.uk/index.htm)获取。这个项目有两部分组成,一个是Aqurate和AqurateAPI,都可以SVN库中检出,算是一个比较好的QTI2实现参考。但其中有一个引用项目中并不包含,即uk.ac.kingston.aqurate.jaxb.imsqti_v2p1包,这个包中的类与接口是从QTI的XSD中通过JAXB转换过来的。我在Koders.com的代码库中找到了这个包(http://www.koders.com/info.aspx?c=ProjectInfo&pid=HKLU3LA68YWE3NFMMAV68EZA3E),但似乎不提供打包下载。
回到主题,完整XSD的下载位置可从这下载:https://qtitools.svn.sourceforge.net/svnroot/qtitools/AquR@te/Trunk/Aqurate/Xsds/
二、JAXB下载
JAXB=Java API for XML Processing。官网:http://jaxb.java.net/#。JAXB教程:
Java Architecture for XML Binding (JAXB):http://www.oracle.com/technetwork/articles/javase/index-140168.html
本文中使用的是JAXB RI 2.2.3,JDK版本是1.6。下载回jaxb的二进制版本后,双击即可解压出jaxb。
Jaxb也提供有Eclipse的plugin,但为了能更灵活的进行配置,本文使用命令行方式从XSD生成JAVA类。
三、执行xjc.bat从XSD生成JAVA类
1、将QTI的相关XSD文件复制到C:\jaxb-ri-20101209\bin文件夹里。在imsqti_v2p1.xsd、imsqti_v2p1g和imsqti_v2p1nm.xsd的内容是一样的,只是import相关XSD的路径不一样,第一个是引用URL,后面两个是本地路径。本文中采用本地编译的XSD,imsqti_v2p1nm不导入MathML。
2、JAXB提供XSD生成JAVA类的命令是xjc.bat,通过cmd进入。
xjc的使用格式是xjc xsd文件名 –p 生成的包名
2.1
当执行xjc imsqti_v2p1nm.xsd –p org.tang 后,出现了错误提示
[ERROR] ‘lang’ is already defined line 93 of http://www.w3.org/2001/03/xml.xsd
[ERROR] <related to above error> the first definition appears here line 5 of file:/C:/java-ri-20101209/bin/xml.xsd
…………….
在imsqti_v2p1nm.xsd可能多次引用xml.xsd了(imslip_v1p0.xsd中也引用了xml.xsd),file:/本的和http://网络的,把imsqti_v2p1nm.xsd第5行
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation= "xml.xsd"/>
改为:<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/03/xml.xsd"/>
可以将其都改为本地的或是网络的
2.2
修改schemaLocation后,重新执行命令:xjc imsqti_v2p1nm.xsd –p org.tang后,仍然出错:
提示多个属性重定义,
[ERROR] Property “Base” is already defined . Use <jaxb:property> to resolve this conflict. line 3990 of file:/C:/jaxb-ri-20101209/bin/imsqti_v2p1g.xsd
…………
就这个问题,在网上查了好多文章,都没有很现成的解决方法。后来在IBM上的一篇文章《JAXB code generation fails with errors》中,看到了相关内容,使用<jaxb:property>解决属性重定义的问题。
2.3
在imsqti_v2p1g.xsd 同目录下新建bindings.xsd文件,内容如下:
<jxb:bindings version="2.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="imsqti_v2p1nm.xsd" node="/xsd:schema">
<jxb:bindings node="//xsd:attributeGroup[@name='printedVariable.AttrGroup']">
<jxb:bindings node=".//xsd:attribute[@name='base']">
<jxb:property name="base0"/>
</jxb:bindings>
</jxb:bindings>
<jxb:bindings node="//xsd:attributeGroup[@name='stringInteraction.AttrGroup']">
<jxb:bindings node=".//xsd:attribute[@name='base']">
<jxb:property name="base1"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
执行命令改为:xjc -b bindings.xsd imsqti_v2p1nm.xsd -p org.tang
成功:
共生成了345个类。