scalaxb 0.1.0

生成されるパーサの一例です:

object Address extends rt.ElemNameParser[Address] {
  val targetNamespace = "http://www.example.com/IPO"

  def parser(node: scala.xml.Node): Parser[Address] =
    (rt.ElemName(targetNamespace, "name")) ~ 
      (rt.ElemName(targetNamespace, "street")) ~ 
      (rt.ElemName(targetNamespace, "city")) ^^
        { case p1 ~ 
      p2 ~ 

xsi:nillable

XML において値の欠如を表現するのに要素を省くか空要素を使うかの方法があります.

未配送の物品,不明な情報,不適切な情報などを要素の欠落ではなく明示的に表現することが望ましい場合があります.

空要素 <foo></foo> を使うことの問題は,空の値が指定されている xs:positiveInteger にマッチしなくなってしまうことです.確かに,正の整数と空文字の両方を許容するために,xs:positiveInteger と空文字のみを含んだ xs:enumeration(列挙型)の xs:union(ユニオン型) を形成することも可能ですが,厳密には空文字と純粋な無の値は別物です.コードでいうと,null"" の違い,特に Scala での NoneSome("") の違いがあります.

XML Schema ではこの問題を解決するために xsi:nil という特別な属性を使います.

<price xsi:nil="true" />

パーサ・コンビネータを使ったパーシング

ハンド・パーシング(手書き構文解析)の限界は前から分かっていました.トークンの位置に頼ったパーシングは,文法に繰り返し,オプション,シーケンスの選択などの複雑なものが出てきたとたんに手に負えなくなります.ある時点で scala のパーサ・コンビネータを使って内容モデルをパーシングをしようと決めましたが,結構長く時間がかかってしまいました.

まずは,実際に使われているスキーマから複雑な構造を紹介しましょう:

<complexType name="SubjectType">
    <choice>
        <sequence>
            <choice>
                <element ref="saml:BaseID"/>
                <element ref="saml:NameID"/>
                <element ref="saml:EncryptedID"/>
            </choice>
            <element ref="saml:SubjectConfirmation" minOccurs="0" maxOccurs="unbounded"/>

混在内容

一つの要素内にテキストノードと子要素が並列して混在している混在内容のサポートを実装しました.<any>と同様にテキストは他のDataRecordオブジェクトと一緒にDataRecord[String]オブジェクトの中に保存され,mixedという値で呼ばれます.

次のようなスキーマがあるとすると,,

<element name="Element3">
  <complexType mixed="true">
    <choice maxOccurs="unbounded">
      <element ref="ipo:Choice1"/>
      <element ref="ipo:Choice2"/>
      <any namespace="##other" processContents="lax" />
    </choice>
  </complexType>
</element>

使用例のコードは以下のようになります.

 

<any> と <anyAttribute>

前回

今後の予定としては,このジェネリックなコンテナを使って現在切り捨てている<any>をちゃんと変換することです.おそらくscala.xml.Elemをそのままの形でコレクションの中に残しておくような形になると思います.一旦ラウンド・トリップ機能を提供すると,ユーザは途中で荷物が無くならないことを期待すると思うので.

と書いたとおり, <any>の処理を変更しました.<any>の処理には2パターンあって,まずsequence の一部として使われる場合.

<element name="Choice1">
  <complexType>
    <sequence>
      <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
  </complexType>
</element>

scalaxb は以下のコードを生成します:

 

ラウンド・トリップ

ラウンド・トリップ(往復券)の実装を始めています.つまり,xmlドキュメントからscalaオブジェクトに変換して,そこからまたxmlドキュメントに変換できるようにする機能です.以下のようなドキュメントがあるとして,

val subject = <shipTo xmlns="http://www.example.com/IPO"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ipo="http://www.example.com/IPO"
    xsi:type="ipo:USAddress">
  <name>Foo</name>
  <street>1537 Paper Street</street>
  <city>Wilmington</city>
  <state>DE</state>
  <zip>19808</zip>
</shipTo>

fromXML()を呼び出すことでオブジェクトに変換できます

val obj = Addressable.fromXML(subject)

名前空間別パッケージ名

名前空間ごとに別のパッケージ内にクラスを生成できるようになりました.

  -p:<namespaceURI>=<package> | --package:<namespaceURI>=<package>
        specifies the target package for <namespaceURI>

例えばXML SignatureとSAML 2.0 assertionは別のパッケージの方がいいですね:

$ scalaxb -p:http://www.w3.org/2000/09/xmldsig#=org.w3.xmldsig -p:http://www.w3.org/2001/04/xmlenc#=org.w3.xmlenc -p:urn:oasis:names:tc:SAML:2.0:assertion=org.xml.saml2.assertion -p:urn:oasis:names:tc:SAML:2.0:metadata=org.xml.saml2.metadata saml-schema-metadata-2.0.xsd saml-schema-assertion-2.0.xsd xenc-schema.xsd xmldsig-core-schema.xsd 

attributes and namespaces in xml

I've heard on occasions that the way attributes work in XML is a mess. It is. The fault is not at attributes per se, but it's the way XML namespace is implemented that's confusing. The spec is called Namespaces in XML 1.0. Try to keep a straight face.

  1. Default namespace declarations do not apply directly to attribute names.
  2. The interpretation of unprefixed attributes is determined by the element on which they appear.
  3. The namespace name for an unprefixed attribute name always has no value.
  4. In all cases, the local name is local part.
  5. No tag may contain two attributes which have identical names.
  6. No tag may contain two attributes which have qualified names with the same local part and with prefixes which have been bound to namespace names that are identical.
  7. All element and attribute names contain either zero or one colon.
  8. No attributes with a declared type of ID, IDREF(S), ENTITY(IES), or NOTATION contain any colons.

<import>, <any>, and simple types

Finally implemented some rough cut of the <import> support. The process is looking more and more like a language compiler. When you are processing multiple XSD schema, the actual parsing step doesn't really care about other files, but the type checking/object binding phase needs to be aware of the other schemas.

In the schema, all you have to do is write

<import namespace="http://www.example.com/IPO"/>

and the types etc. from the given namespace are imported to the current schema. So, this works more like Java's import than C's #include, which is limited to inclusion of a physical file.

xml namespace

I've been working on Issue 1 submitted by Tsuresh Kumar for a while now. The idea is to compile the schema for SAML Metadata, which is saml-schema-metadata-2.0.xsd. I need to implement a few things so scalaxb can handle the schema.

Syndicate content