JAXBを使用するこのAPIを使用して、XJC(XML-to-Java)コンパイラーによってXMLスキーマから名前付き参照を介して生成されたオブジェクトモデルを便利に使用できます。これは、JAXBコンテキストの作成を抽象化し、あらゆる種類のバックグラウンドマジックとリフレクションによってObjectFactoryメソッドを見つけ出します。その基本的な要点は、常に1つの一般的なスキーマを定義し、次にその一般的なスキーマを「拡張」する任意の数(0の場合もある)のスキーマを定義し、それぞれが独自のデータモデルを作成することです。一般的なスキーマには再利用可能な定義があり、それを拡張するスキーマはそれらを使用して独自のモデルを構成します。
現在、複数のプロジェクトで一般的なスキーマを再利用したいという状況に遭遇しました。一般的な型の定義はプロジェクト間で同じである必要があり、一部のコードはそれらから生成された抽象クラスに対して構築されます。したがって、最初にいくつかの汎用スキーマのクラスを生成し、次にそれらを拡張して個別に使用するクラスを生成する必要があります。ビルドプロセスにMavenを使用しています。
私が直面している問題は、拡張スキーマ内のそのジェネリックスキーマから型定義を解決することです。
私の汎用スキーマの名前が「general.xsd」で、次のようになっているとします。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foobar.com/general"
xmlns:gen="http://www.foobar.com/general"
elementFormDefault="qualified" attributeFormDefault="qualified">
<!-- Element (will usually be root) -->
<xs:element name="transmission" type="gen:Transmission" />
<!-- Definition -->
<xs:complexType name="Transmission" abstract="true">
<xs:sequence>
<!-- Generic parts of a transmission would be in here... -->
</xs:sequence>
</xs:complexType>
</xs:schema>
その隣に、名前のカスタマイズを行い、出力のパッケージ名を設定するためのバインディングファイルがあります。
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<!-- Bindings for the general schema -->
<bindings schemaLocation="general.xsd" node="/xs:schema">
<schemaBindings>
<package name="com.foobar.models.general"/>
</schemaBindings>
<bindings node="//xs:complexType[@name='Transmission']">
<!-- Some customization of property names here... -->
</bindings>
</bindings>
次に、そのプロジェクトのPOMに次のビットを入れて、Javaクラスを生成します。
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb21-plugin</artifactId>
<version>0.8.0</version>
<executions>
<execution>
<id>xjc-generate</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaDirectory>${basedir}/src/main/resources/com/foobar/schemas</schemaDirectory>
<schemaLanguage>XMLSCHEMA</schemaLanguage>
<addCompileSourceRoot>true</addCompileSourceRoot>
<episode>true</episode>
<removeOldOutput>true</removeOldOutput>
</configuration>
</execution>
</executions>
</plugin>
ご覧のとおり、私はJAXB2.1Mavenプラグインを使用しています。段階的なコンパイルのためにエピソードファイルを生成するオプションを設定しました。以前の出力を削除するオプションは、バグの回避策でした。最初にすべてがクリーンアップされていることを確認して、再コンパイルを強制するだけです。
ここまでは順調ですね。そのプロジェクトは問題なくコンパイルされます。生成されたJavaクラスとは別に、スキーマを結果のjarファイルにパッケージ化することにも注意してください。したがって、それらはクラスパスで利用できます。ファイルは、sun-jaxb.episode
本来あるべきMETA-INFにあります。
次に、最初にインポートすることにより、上記を拡張するスキーマを使用するプロジェクトを開始します。「サブタイプ」の1つは次のようになります(これをsub.xsdと呼びます)。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foobar.com/sub"
xmlns:sub="http://www.foobar.com/sub"
xmlns:gen="http://www.foobar.com/general"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:import namespace="http://www.foobar.com/general" />
<!-- Definition -->
<xs:complexType name="SubTransmission">
<xs:complexContent>
<xs:extension base="gen:Transmission">
<xs:sequence>
<!-- Additional elements placed here... -->
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
ここでも、バインディングファイルがあります。
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<!-- Bindings for sub type -->
<bindings schemaLocation="sub.xsd" node="/xs:schema">
<schemaBindings>
<package name="com.foobar.models.sub"/>
</schemaBindings>
</bindings>
</bindings>
そして、XJC生成を処理するこのプロジェクトのPOMからのビットは次のとおりです。
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb21-plugin</artifactId>
<version>0.8.0</version>
<executions>
<execution>
<id>xjc-generate</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaDirectory>${basedir}/src/main/resources/com/foobar/schemas</schemaDirectory>
<schemaLanguage>XMLSCHEMA</schemaLanguage>
<addCompileSourceRoot>true</addCompileSourceRoot>
<episode>false</episode>
<catalog>${basedir}/src/main/resources/com/foobar/schemas/catalog.cat</catalog>
<episodes>
<episode>
<groupId>com.foobar</groupId>
<artifactId>foobar-general-models</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</episode>
</episodes>
<removeOldOutput>true</removeOldOutput>
</configuration>
</execution>
</executions>
</plugin>
元々、すべてのスキーマは1つのフォルダーにありschemaLocation
、インポートの属性をに設定してgeneral.xsd
いましたが、これは正常に機能しました。しかし、物事がプロジェクト間で分離された今、私は問題にぶつかります。最初の問題は、他のスキーマが見つからなかったことです。これを解決schemaLocation
するには、<xs:import />
要素から属性を削除し、属性のみを保持し、上記のPOM抽出で参照されてnamespace
いるカタログファイル()を追加します。catalog.cat
その内容は次のとおりです。
PUBLIC "http://www.foobar.com/general" "classpath:/com/foobar/schemas/general.xsd"
スキーマが見つからないことを示すエラーが発生しなくなったため、これは機能しているようです。しかし、何らかの理由で、インポートされたスキーマからの実際の型定義の解決は引き続き失敗します。例外は次のとおりです。
Error while parsing schema(s).Location [ file:/C:/NetBeans_groups/Test/SubModelBundle/src/main/resources/com/foobar/schemas/sub.xsd{...,...}].
org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'gen:Transmission' to a(n) 'type definition' component.
これが私がこれまでに試したことです:
- カタログファイルを使用します。インポートされたスキーマが見つかるようになったため、部分的に成功しました。
- 一般スキーマのコンパイルでエピソードファイルを生成し、これをサブスキーマのコンパイルに使用します。違いはないようですが、これはタイプが解決された後にのみ役割を果たすはずなので、これはまだ重要ではないと思います。
- 別のJAXP(注:JAXB、JAXPではない)実装を使用してください。例外のスタックトレースでそれを確認できたので、別のものを使用しましたが、最終結果は同じです。
maven-jaxb22-plugin
21の代わりに使用してください。違いはありません。
オンラインで見てみると、少なくとも2006年以来、人々はこの問題に遭遇しているようであり、Xercesリゾルバーの問題に関連している可能性があります。これが、誰も気にせずに6年間潜んでいるバグではないことを願っています。他の誰かがいくつかの提案がありますか?たぶん誰かが同じ問題に遭遇し、解決策を見つけましたか?私が考えることができる唯一の回避策は、「svn:externals」を使用して一般的なスキーマをサブプロジェクトにドラッグし、そこでクラスを再生成することですが、それはダーティであり、svnリポジトリに接続できる場合にのみ機能します。
この長い投稿を読んでくれてありがとう。上記のすべてを既存のプロジェクトから取り除いて、匿名性のためにいくつかの名前空間やその他のものを置き換えたことを覚えておいてください。そのため、いくつかのタイプミスが発生する可能性があります。