[[FrontPage]] * rngomでXMLSchemaのDatatypeLibraryを使う [#z66b4e28] ** rngom とは [#yb7f7ea2] [[rngom>https://rngom.dev.java.net/]] (RelaxNG Object Model) は,RelaxNG のスキーマを扱うツールを作るためのライブラリです.rngom は,[[Jing>http://www.thaiopensource.com/relaxng/jing.html]]という,RelaxNGの validator をベースに開発されています. 私は,rngom で XMLSchema の datatype library を使おうとしてはまったので,その解決方法のメモです. ''以下は,試行錯誤の結果,見つけた解決法です.間違いが含まれている可能性があります'' ** 問題 [#nf22b0e2] rngom で XMLSchema の datatype library を使うには,[[xsdlib>https://msv.dev.java.net/servlets/ProjectDocumentList?folderID=101&expandFolder=101&folderID=100]] が必要です.xsdlib.jar を CLASSPATH に追加することで,利用可能になります. しかし,単にこれを使っても,XMLSchema の datatype を利用できませんでした. 制約チェックをして,パースする場合,[[RNGOM User's Guide>https://rngom.dev.java.net/nonav/doc/users-guide.html]] によると,次のようになります. import org.kohsuke.rngom.ast.util.CheckingSchemaBuilder; Parseable parseable = ...; YourParsedPattern = (YourParsedPattern)parseable.parse(new CheckingSchemaBuilder(schemaBuilder,errorHandler)); もっと,具体的なコードで書くと,例えば,次のようになります. import org.kohsuke.rngom.ast.util.CheckingSchemaBuilder; import org.kohsuke.rngom.binary.SchemaBuilderImpl; import org.kohsuke.rngom.parse.Parseable; import org.kohsuke.rngom.parse.xml.SAXParseable; Parseable parseable = new SAXParseable(source, errorHandler); ParsedPattern = parseable.parse(new CheckingSchemaBuilder(new SchemaBuilderImpl() ,errorHandler)); しかし,このコードでは,xsdlib.jar があっても,XMLSchema の datatype が使えません. ** 原因と解決法 [#t301bab9] datatype を定義するには,org.relaxng.datatype.DatatypeLibrary や,org.relaxng.datatype.DatatypeLibraryFactory を実装します. datatype を識別するURIから適切な DatatypeLibrary を返すのは,DatatypeLibraryFactory の実装の仕事です. 問題は,SchemaBuilderImpl です.引数が ErrorHandler のみのコンストラクタで構築すると,コンストラクタは,DatatypeLibraryFactory の実装として org.kohsuke.rngom.dt.builtin.BuiltinDatatypeLibraryFactory を使います. ところが,org.kohsuke.rngom.dt.builtin.BuiltinDatatypeLibraryFactory は,XMLSchema の datatype の URI (http://www.w3.org/2001/XMLSchema-datatypes) を受け付けません. 次のような実装になっているからです. public DatatypeLibrary createDatatypeLibrary(String uri) { if (uri.equals("")) return builtinDatatypeLibrary; if (uri.equals(WellKnownNamespaces.RELAX_NG_COMPATIBILITY_DATATYPES)) return compatibilityDatatypeLibrary; return null; } 代わりに,org.relaxng.datatype.helpers.DatatypeLibraryLoader を使えば,CLASSPATH から,META-INF/services/org.relaxng.datatype.DatatypeLibraryFactory を探して,その内容を元にして org.relaxng.datatype.DatatypeLibraryFactory の実装を見つけてくれるので,xsdlib.jar が提供する XMLSchema の datatype library を使うことが出来ます. CheckingSchemaBuilder も内部で SchemaBuilderImpl を使っているので,こちらにもDatatypeLibraryFactory を渡してやる必要があります. コードは,次のようになります. import org.kohsuke.rngom.ast.builder.SchemaBuilder; import org.kohsuke.rngom.ast.om.ParsedPattern; import org.kohsuke.rngom.ast.util.CheckingSchemaBuilder; import org.kohsuke.rngom.binary.SchemaBuilderImpl; import org.kohsuke.rngom.binary.SchemaPatternBuilder; import org.kohsuke.rngom.parse.Parseable; import org.relaxng.datatype.DatatypeLibraryFactory; import org.relaxng.datatype.helpers.DatatypeLibraryLoader; import org.xml.sax.ErrorHandler; ... ErrorHandler errorHandler = ...; Parseable parseable = ...; DatatypeLibraryFactory datatypeLibraryFactory = new DatatypeLibraryLoader(); SchemaBuilder schemaBuilder = new SchemaBuilderImpl(errorHandler, datatypeLibraryFactory, new SchemaPatternBuilder()); ParsedPattern pattern = parseable.parse(new CheckingSchemaBuilder(schemaBuilder, errorHandler, datatypeLibraryFactory));