/ja?>
RelaxNGCC独自のマークアップはすべて
http://www.xml.gr.jp/xmlns/relaxngcc
のnamespace-URIを持ちますが、このマニュアルではプレフィックス "c" を使用しています。マークアップは次に説明するように3種のエレメントと5種のアトリビュートから構成されます。
/ja?>
all the attributes and elements defined in RelaxNGCC uses http://www.xml.gr.jp/xmlns/relaxngcc as the namespace URI. In this manual, we assume the prefix "c" is bound to this namespace URI.
/en?>
ユーザ定義のコードからアクセスするために、データに名前をつけます。この変数名で、生成されたクラス内にフィールドが追加されます。このアトリビュートをつけることのできるRELAX NGのエレメントは、data, text, ref, value, listの5つです。 /ja?> Adding this attribute to a RELAX NG pattern will cause the compiler to declare a field declaration inside the generated class. At run-time, if a string in an XML document matches the pattern, then the generated code stores that value to this field. This makes it possible for your code to acess those values. This attribute is applicable to the data, text, ref, value, and list pattern. /en?>
<data type="nonNegativeInteger" c:alias="count"/>
ref/parentRefパターンにc:aliasをつけた場合、それらが参照する先のスコープで戻り値として指定された値が得られます(一般には、これはスコープに対応するRelaxNGCCが生成したクラスそのものです)。 /ja?> Adding c:alias attribute to a ref or parentRef pattern will cause the specified variable to receive the value specified as the return value in the refrenced scope. By default, this is an instance of the generated class that was used to parse the referenced scope. /en?>
listパターンにc:aliasをつけたときにはリスト全体が1個の文字列として取り出されます。 /ja?> A c:alias attribute on a list pattern will cause the entire string (that matches to the whole list pattern) to be anchored. /en?>
ユーザ定義のJavaコードを記述します。コードからc:aliasアトリビュートで定義した名前を使うことができます。記述したコードは、入力XMLの該当個所を読んだところで実行されます。/ja?> You can write a code fragment of Java in a c:java element. Within this fragment, you can refer to the data of an XML document by fields declared through alias attribites. The content of java element is executed when the input hits the position where the c:java element is written./en?>
<element name="name"> <text c:alias="name"/> <c:java>System.out.println(name);</c:java> </element>
生成されたコードは最終的にはSAX2ベースの処理になるので、外に投げることのできる例外はSAXExceptionとその派生クラスに限られます。/ja?> The code fragment can throw SAXExceptions (or unchecked exceptions, as usual.)/en?>
javaエレメントはchoice, interleave以外の子パターンをとる全てのパターンの中に書けます(start, define, group, optional, zeroOrMore, oneOrMore, mixed, listパターンの中)。 /ja?> A java element can be written inside any pattern that can take child patterns except choice and interleave (that is, as a child of start, define, group, optional, zeroOrMore, oneOrMore, mixed, and list.) /en?>
なおエレメント名にjavaを使っている理由は、将来他のプログラム言語(例えばC#)にも対応するかもしれないからです。/ja?> Note that the reason why we use the keyword "java" as an element name is that we are planning to support other languages (such as C#) in the future./en?>
生成されるクラスについて、補助的に使用するメソッドやデータメンバを記述します。ここで定義したものはjavaエレメント内のコードからアクセスできます。 /ja?> The body of this element is copied inside the body of the generate classes. Thus this is usually used to declare additional fields or helper methods. /en?>
<define name="x">
<c:java-body>
private void echo(String msg) {
System.out.println(msg);
}
</c:java-body>
...
</define>
たとえばこのようにすると、このdefineブロックのjavaエレメント内からechoメソッドが使えるようになります。/ja?> For example, With the above declaration, the echo method becomes available from all the java elements in this define block. /en?>
java-bodyエレメントは、次の場所に書くことができます。/ja?> A java-body element can be written only as children of the following patterns:/en?>
java-bodyと違い、ソースコード中のクラス定義本体の外に記述するコードを記述します。ふつうJavaのimport宣言を記述します。これを置くことのできる位置と効果はjava-bodyと同じです。/ja?> Works similar to c:java-body elements. The only difference is that the contents of a java-import element is copied before the definition of a class. Hence one would usually write import declarations by using the java-import element. /en?>
<c:java-import> import java.util.Set; import java.util.Iterator; </c:java-import>
startエレメント、defineエレメントに記述して、それに対応するクラスの名前を指定します。Javaのクラス名として正しい文字列を指定する必要があります。省略時には、RelaxNGCCが適当な名前をつけてソースコードを生成します。 /ja?> The class attribute can appear at a start pattern or a define pattern, and specifies the name of the generated Java class. The value of class attribute must be a valid Java class. If it is omitted, RelaxNGCC generates a name for the class. /en?>
<start c:class="Root"> ... </start>
生成するソースコードがどのパッケージに属すかを指定します。ルートエレメントに記入します。この宣言は生成されるすべてのクラスに対して有効です。 /ja?> The package attribute can appear only on the root element of RELAX NG. Adding this attribute will cause a compiler to add the package declaration to all the files it generates. /en?>
<grammar ... c:package="com.example.project1"> ...
生成するソースコードのアクセス修飾子("public final"など)を指定します。このアトリビュートはdefineエレメント、startエレメント、classアトリビュートを書いたエレメントに書くことができます。 /ja?> The c:access attribute causes the compiler to add the specified access modifiers (such as "public final") to the generated Java class. Only define and start pattern can carry this attribute. /en?>
<start c:class="sample1" c:access="public final"> ... </start>
This attribute causes the compiler to use a user-defined runtime class instead of the default NGCCRuntime class. The value of the attribute must be a valid Java class that is derived from NGCCRuntime. /en?> 標準のNGCCRuntimeクラスの代わりに、この属性で指定されたユーザー定義のクラスを使うようにコンパイラに指示します。 /ja?>
Only the root element (usually a <grammar> pattern) in the source schema can carry this attribute. /en?> この属性は、RELAX NG文法ファイルのルート要素でのみ指定可能です。 /ja?>
<?xml version="1.0"?> <grammar c:runtime-type="org.acme.foo.MyNGCCRuntime" ...> .... </grammar>
These attributes can be specified on <define> and <start patterns, to specify the return value from a handler class. /en?> これらの属性を指定することで、生成されたハンドラクラスからの戻り値を指定できるようになります。これらの属性は、どちらも<define>か<start>パターンに対して指定可能です。 /ja?>
c:return-value specifies the expression that will be evaluated to the return value from a handler, and c:return-type specifies its type. The return value will be assigned to the alias specified on the corresponding <ref> element. c:return-value defaults to "this", hence by default the handler object itself will be returned and assigned to the alias. /en?> c:return-value属性には、戻り値として評価される式を書きます。子ハンドラが処理を終了して親ハンドラに戻る際に、この式が評価されて結果が親ハンドラに返ります。親ハンドラ側では、c:alias属性を使って戻り値にアクセスすることができます。c:return-type属性は、この戻り値の型を指定します。ディフォルトでは、c:return-valueは"this"になっているので、ハンドラ自身が返されます。 /ja?>
In the following example, makeResult method will be called and the return value from that method will be returned from the handler. /en?> 次の例では、makeResult関数が呼び出されて、その値が戻り値となります。 /ja?>
<define name="foo" c:return-type="String" c:return-value="makeResult()"> <c:java-body> private String makeResult() { .... } </c:java-body> ... </define> ... <ref name="foo" c:alias="someStringVariable">
These two annotations are used together to allow a parent handler to pass parameters to the a handler. /en?> これらの属性は対で利用され、親ハンドラから子ハンドラへパラメータを渡すのに使われます。 /ja?>
The c:params attribute can be specified on <define> and <start elements to declare parameters. When a c:params is present, the c:with-params needs to be specified on the corresponding <ref> elements. /en?> c:params属性は、<define>か<start>パターンに対して指定でき、パラメータを宣言します。一方、c:with-params属性は、パラメータつきで宣言された<define>を参照する<ref>パターンに対して指定します。 /ja?>
The value of the c:params attribute must be a camma(',')-separated list of type and variable name pairs, just like when you define arguments of a function. The value of the c:with-params attribute must be a camma-separated list of Java expressions, again just like when you invoke a method. /en?> c:params属性の値は、カンマ区切りの型-変数名ペアで、ちょうど関数を宣言する時のパラメータリストと同じ書式です。c:with-paramsは、同じくカンマ区切りの式の並びで、やはりちょうど関数を呼び出す時と同じ書式です。 /ja?>
Once you specify a c:params attribute on a block, you need to have c:with-params attributes on all the <ref/> patterns that refer to it. /en?> あるブロックをc:params付きで宣言すると、そのブロックを参照する全ての<ref/>パターンにc:with-paramsが必要になるので注意してください。 /ja?>
The compiler generated fields by the same name, and passed parameters are assigned to those fields, so you can access them from <c:java-body> or <c:java>. /en?> 渡されたパラメータは、同名で生成されたフィールド変数にコピーされるので、<c:java-body>や<c:java>の中からアクセスできます。 /ja?>
<define name="foo" c:params="String a,boolean b,Object c"> ... <c:java> System.out.println(a); </c:java> </define> ... <ref name="foo" c:with-params='"xyz",true,null' /> ... <ref name="foo" c:with-params='"test",false,System.out' />
RelaxNGCCが生成したコードをコンパイルしたり実行するには、JAXP対応のXMLパーサが必要です/ja?> To compile and run the code generated by RelaxNGCC, a JAXP-compliant XML parser is necessary. /en?>
生成したコードは、SAX2イベントを生成するあらゆるコンポーネントと組み合わせて利用可能です。SAX2イベントから生成されたコードを駆動する方法については、もとの文法のstartエレメントに対応したクラスに付加されるmain()関数を参照してください。 /ja?> The generated code will work with any component that produces SAX2 events. For details, please refer to the main() function located at the class corresponding to the start pattern. /en?>
RelaxNGCCはコンストラクタを自分で生成するため、そのままではコンストラクタを書き換えることはできません。オブジェクトの生成時の処理を追加するには、イニシャライザを利用してください。 /ja?> RelaxNGCC uses the consturctor of the generated classes for its own purpose. This makes it impossible to customize the constructors through c:java-body elements. To add code executed at the instanciation of an object, use the instance initializer: /en?>
<define name="foo"> <c:java-body> {// add your code here System.out.println("initializer"); } </c:java-body>
RelaxNGCCでは、どんな文法も読み込めるわけではなく、先読み1個で分岐を判断できる文法だけを受け付けます。 /ja?> There are grammars that cannot be handled by RelaxNGCC. Specifically, a grammar cannot be handled by RelaxNGCC if it needs a look-ahead. /en?>
<choice> <group> <element name="a"><text/></element> <c:java>System.out.println("a0");</c:java> <element name="x"><text/></element> </group> <group> <element name="a"><text/></element> <c:java>System.out.println("a1");</c:java> <element name="y"><text/></element> </group> </choice>
このようなとき、最初にaエレメントをみただけではどちらのchoiceが正しいのかは判定できません。先読みをすればxまたはyがきて判定可能になりますが、RelaxNGCCはこのような判定はできません。次のように書き換える必要があります。/ja?> In the above sample, correct branching on the choice pattern cannot be done until you read the next element, because both children of the choice starts with the a element. To avoid this, the grammar needs to be rewritten as follows:/en?>
<group> <element name="a"><text/></element> <choice> <group> <element name="x"><text/></element> <c:java>System.out.println("a0");</c:java> </group> <group> <element name="y"><text/></element> <c:java>System.out.println("a1");</c:java> </group> </choice> </group>
文法がこの制約を満たさないとき、RelaxNGCCは警告メッセージを発します。特に文法があいまいな場合にはどう変形してもこの制約を逃れることができなくなるので注意が必要です。/ja?> If a grammar violates this restriction, RelaxNGCC raises a warning message. Note that some grammars are unable to rewrite in an unambigous way./en?>
情報科学の言葉で言えば、defineやstartブロックを、SAXイベントを終端記号とした文脈自由文法として解釈したとき、それがLL(1)であるときに限りRelaxNGCCは取り扱えます。このあたりの議論はコンパイラの教科書に詳しく載っています。/ja?> In terms of information science, when we interpret the given RELAX NG grammar as a context free grammar by treating every SAX event as a terminal symbol, RelaxNGCC can treat only if that grammar is LL(1)./en?>
RELAX NGの仕様のうち、次の機能はまだサポートされていません。将来のバージョンで徐々に実装するつもりです。/ja?> RelaxNGCC does not support the following features of RELAX NG. Hopefully they will be implemented in a future version./en?>