倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

MarkupBuilder で RELAX NG スキーマを書いてみた

MarkupBuilder でスタイルシートを書いてみた』ついでに、MarkupBuidler で RELAX NG スキーマも書いてみました。

RELAX NG には、XML 形式でない簡略化された記法『RELAX NG Compact Syntax』というのがあるのであえて MarkupBuilder を使う必要はないかも知れませんが、Compact Syntax に対応していない Java ライブラリでもこの方法は使えるので一定のメリットはあるかと。

妥当性検証対象の XML データ


妥当性検証の対象として使用するサンプルの XML データは『MarkupBuilder でスタイルシートを書いてみた』で用いたものを使うことにします。

Groovy の Builder を用いた RELAX NG スキーマ


RELAX NG スキーマの構築も、以前のスタイルシートの構築とやってることは同じです。

まずは MarkupBuilder の準備。 ここでも RELAX NG スキーマを文字列に書き出すために StringWriter を用いています。

def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)

ではスキーマの構築。 名前空間を使う必要がない場合はシングルクォート (') で囲む必要もないのでスタイルシートの場合よりも簡単。

builder.grammar(xmlns:XMLConstants.RELAXNG_NS_URI){

    start{
        element(name:'Groovy-Projects'){
            oneOrMore{ ref(name:'GroovyProject') }
        }
    }

    define(name:'GroovyProject'){
        element{
            anyName{}
            attribute(name:'latest-version'){}
            element(name:'url'){ text{} }
            element(name:'description'){ text{} }
        }
    }
}

RELAX NG Compact Syntax に比べて oneOrMore など(他にも zeroOrMore, optional など)がちょっと助長な感じもしますが。

後は構築したスキーマを用いて妥当性検証を行います。 以下の例では javax.xml.validation パッケージを用いて妥当性検証を行っています:

def schemaSource = new StreamSource(new StringReader(writer.toString()))
def schema = RelaxngSchemaFactory.newFactory().newSchema(schemaSource)
def validator = schema.newValidator()
validator.validate(new StreamSource("sample.xml"))
public class RelaxngSchemaFactory {

    public static SchemaFactory newFactory(){

        try{
            return SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

        }catch(IllegalArgumentException ex){

            for(SchemaFactory factory: ServiceLoader.load(SchemaFactory.class)){

                if(factory.isSchemaLanguageSupported(XMLConstants.RELAXNG_NS_URI))
                    return factory;
            }

            throw ex;
        }
    }
}

まぁ、スタイルシートのときとあんまり変わらないですね。

Groovyイン・アクション

Groovyイン・アクション


Relax Ng

Relax Ng