XML XSD 基本から 初心者用 その3

なのでここからは残り3%をチョロチョロ追記仕様と思います。 これが最後のページです。 これを最後まで出来たらあなたはもうxsd、xmlは怖くないと思います。 xsdにはまだまだ数え切れないくらいの定義がありますが、Microsoft Excelも全部を使うには10年かかると言われていますが、普通2~3日で使い始めて、式や、マクロやピボットを使っても多分1/10しか使っていないと思いますが、全然問題ありません。 日本語も知らない言葉も無数にありますが十分使えます。xsdも同じです。 ここを終了して始めてみましょう。

xs:redefine

  • 既存の XSD の定義を**物理的に書き換える(オーバーライドする)**唯一の手段です。 redefine の真骨頂は、単なる要素の追加だけでなく、 「既存の制約(長さ制限など)を上書き・強化する」 ことにあります。
  • redefineできるのは同じNamespace URIである必要があります。
  • 以下にbase.xsdとi.xsdがあります。両方Namespace URIはtargetNamespace=”https://dx.ichiri.biz”です。
  • まずbase.xsdを読み込んで、NameTypeの最大100文字長であるのを20に上書きしています。 この時型はxs:simpleTypeのままなのでxs:extensionは要りません。
  • 次にemailというタグを追加します。 その時xs:elementが増えるので、tns:UserTypeと自分を拡張(xs:extension)しなければなりません。
  • この時xs:complexContentがありますが、「この型は『継承』や『上書き』を行う特別な構造である」と宣言するためのマーカーです。 通常の xs:complexTypeはゼロから中身を定義しますが、既存の定義を使い回す(redefine, extension, restriction)場合には、このタグで囲むことが xsdの文法上の絶対ルール です。
  • xs:simpleTypeの中にはxs:restriction(制約)、xs:list(リスト化)、xs:union(結合)の3種類しか記述できず、xs:simpleContent や xs:complexContent を書いた瞬間に XSD バリデーターは「文法エラー」として停止するので、以下のxs:simpleTypeにはxs:simpleContent や xs:complexContentを使いません。
  • xs:complexTypeを『継承』や『上書き』を行う場合、type(データ型)を変える場合や追加するや制限する場合だけなどxs:elementを増やさない場合はxs:simpleContentを使い、下の例の様にxs:elementを追加する場合はxs:complexContentを使わなければなりません。
base.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="https://dx.ichiri.biz"
           xmlns:tns="https://dx.ichiri.biz"
           elementFormDefault="qualified">

  <xs:simpleType name="NameType">
    <xs:restriction base="xs:string">
      <xs:maxLength value="100"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:complexType name="UserType">
    <xs:sequence>
      <xs:element name="name" type="tns:NameType"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>
i.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="https://dx.ichiri.biz"
           xmlns:tns="https://dx.ichiri.biz"
           elementFormDefault="qualified">

  <xs:redefine schemaLocation="base.xsd">
    <xs:simpleType name="NameType">
      <xs:restriction base="tns:NameType">
        <xs:maxLength value="20"/>
      </xs:restriction>
    </xs:simpleType>

    <xs:complexType name="UserType">
      <xs:complexContent>
        <xs:extension base="tns:UserType">
          <xs:sequence>
            <xs:element name="email" type="xs:string"/>
          </xs:sequence>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>

  <xs:element name="ichiri-app">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="user" type="tns:UserType" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
i.xml
<?xml version="1.0" encoding="UTF-8"?>
<abc:ichiri-app xmlns:abc="https://dx.ichiri.biz"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="https://dx.ichiri.biz extended.xsd">

  <abc:user>
    <abc:name>Ichiriyama</abc:name>
    <abc:email>admin@ichiri.biz</abc:email>
  </abc:user>

</abc:ichiri-app>

xs:annotation

  • これはメモのようなもので、xmlバリデーターには無視されます。 しかしここが私達が唯一自由に使えるmetaデーター領域です。
  • xs:annotationで大外をくくり、使えるのはxs:documentかxs:appinfoのどちらか。
    • xs:document:人が読む用、又はAIに読ますツールチップ
    • xs:appinfo:コンピューターが読む、API接続定義やバリデーションロジック
  • 最初のxs:documnetは、メモの様に書き込める。 リンクがあればブラウザでこのxmlを表示したらリンク表示してくる。
  • 次のxs:documentは、htmlを中に書ける。 ブラウザでこのxmlを表示したら、htmlとしてキレイに表示してくれる。
  • 3つ目のxs:documentは、xs:document内には自由にタグを作れる。 xs:annotation内はバリデーターは無視する。 Namespace URIはtargetNamespaceと同じでもよいが下はdocを付けてる。 そしてこの場合xyzというnamespaceを定義しておく
  • xs:appinfoも同じ。
  • ところで最後のxs:simpleTypeがあるが、nameがなく、どのにもtns:<simlpeTypeName>で指定されていない。 これは匿名型といってnameがなく、すぐ上のxs:elementに追加されます。 この場合だとかなり上になりますが<xs:element name=”ichiri-id”>となります。
i.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="https://dx.ichiri.biz/schema"
           xmlns:tns="https://dx.ichiri.biz/schema"
           xmlns:ui="https://ui.ichiri.biz" 
           elementFormDefault="qualified">

  <xs:element name="ichiri-id">
    <xs:annotation>
      <xs:documentation xml:lang="ja">
        ichiri-platformの認証ID。8桁の英数字を書くようにしてね。 誰かこれ読んでね。
        <a href="https://ichiri.biz/docs/spec.pdf">認証仕様書(PDF)</a>
      </xs:documentation>

      <xs:documentation xml:lang="ja">
        <p>ichiri-platformの<b>認証ID</b>です。</p>
        <ul>
          <li>8桁の英数字のみ許可</li>
          <li>大文字・小文字を区別しない</li>
        </ul>
      </xs:documentation>

      <xs:documentation xmlns:xyz="https://dx.ichiri.biz/doc">
        <xyz:summary>認証ID定義</xyz:summary>
        <xyz:remarks>この項目はichiri-dbの主キーと連動します。</xyz:remarks>
      </xs:documentation>

      <xs:appinfo>
        <ui:config>
          <ui:component>InputMask</ui:component>
          <ui:mask>9999-9999</ui:mask>
          <ui:db-mapping>ichiri-db.auth_table.id</ui:db-mapping>
        </ui:config>
      </xs:appinfo>
    </xs:annotation>

    <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:pattern value="[A-Z0-9]{8}"/>
      </xs:restriction>
    </xs:simpleType>
  </xs:element>

  <xs:element name="ichiri-app-dx">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:ichiri-id"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>
i.xml
<?xml version="1.0" encoding="UTF-8"?>
<abc:ichiri-app-dx xmlns:abc="https://dx.ichiri.biz/schema"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="https://dx.ichiri.biz/schema i.xsd">

  <abc:ichiri-id>ABC12345</abc:ichiri-id>

</abc:ichiri-app-dx>

GCP、AWS、Azure等で使う場合

Google CloudでAnuglar AppやDBやCloud Run使う時、appinfoでプロトコルを作って、このxsdを使ったら、どのui component使って、どのDB(テーブル名、クエリ、インデックス等)使って、どのDockerやLambdaやCloud Runを走らす名前(関数名、引数など)で制御するなどの情報をxsdに入れておくことができます。 xs:annotation内はバリデーターはチェックしないので自由に書けます。自分のプログラムでパースすして使わなければどこにも使われません。

i.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="https://dx.ichiri.biz/schema"
           xmlns:tns="https://dx.ichiri.biz/schema"
           xmlns:ui="https://ui.ichiri.biz"
           xmlns:db="https://db.ichiri.biz"
           elementFormDefault="qualified">

  <xs:element name="ichiri-id">
    <xs:annotation>
      <xs:appinfo>
        <ui:control>
          <ui:component>IchiriInput</ui:component>
          <ui:theme>primary</ui:theme>
          <ui:autofocus>true</ui:autofocus>
        </ui:control>
        <db:persistence>
          <db:table>users_meta</db:table>
          <db:column>identity_key</db:column>
          <db:encryption>AES256</db:encryption>
        </db:persistence>
        <logic:flow xmlns:logic="https://logic.ichiri.biz">
          <logic:on-success>https://ichiri-hub.biz/v1/next-step</logic:on-success>
          <logic:on-error-hook>ichiri-app-dx-error-logger</logic:on-error-hook>
        </logic:flow>
      </xs:appinfo>
    </xs:annotation>
    <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:pattern value="[A-Z0-9]{8}"/>
      </xs:restriction>
    </xs:simpleType>
  </xs:element>
</xs:schema>

xs:element substiutionGroup属性

  • xs:elementでabstric=”true”があると、そのxs:elementはbase-idとしてははxmlでは書くとエラーなります。
  • しかしsubstitutionGroupのnameを使ってxs:elementをxmlに表示できます。
  • 下の例では使用したいタグ名が3つあって、どれでも使えるようになります。
  • これによりシステムへ受け渡すタグ名を変数名や関数名やDBを名等として変えることが出来ます。
  • 上記appinfoは内部に隠せる変数として使います。
  • これはxmlに表示して書類として処理を変更する時に使います。
  • substitutionGroupはxs:element専用です。
  • abstructはxs:elementとxs:complexTypeで使います。 
i.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="https://dx.ichiri.biz/schema"
           xmlns:tns="https://dx.ichiri.biz/schema"
           elementFormDefault="qualified">

  <xs:element name="base-id" abstract="true" type="xs:string"/>

  <xs:element name="ichiri-id" substitutionGroup="tns:base-id" type="xs:string"/>
  <xs:element name="admin-id"  substitutionGroup="tns:base-id" type="xs:string"/>
  <xs:element name="user-id"  substitutionGroup="tns:base-id" type="xs:string"/>

  <xs:element name="ichiri-app-dx">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:base-id"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>
i.xml
<?xml version="1.0" encoding="UTF-8"?>
<abc:ichiri-app-dx xmlns:abc="https://dx.ichiri.biz/schema"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="https://dx.ichiri.biz/schema i.xsd">

  <abc:ichiri-id>USER0001</abc:ichiri-id>

</abc:ichiri-app-dx>
  • 上記は、3つのsubstitutionGroup候補から1個しか作れませんでした。
  • 以下があり、substitutionGroup候補が1000個あれば1000個までなら何個でもxs:elementとしてタグを作れます。
<xs:element ref="tns:base-id" maxOccurs="unbounded"/>
  • xs:complexTypeもxs:elementと似てますがちょっとちがうのでややこしいです。
  • xs:elementは、1つのabstructのxs:elementに、複数のsubstitutionGroupから1個なり複数が置き換わりました。 しかしxs:comlexTypeは、abstructのxs:compleTypeが、以下の例ではその下2つのxs:compleTypeに入ります。 そしてそのどれかを選ぶことになります。
  • この場合だと、tns:UserTypeだとtns:id-valueとtns:regionのxs:elementの組み合わせ。 tns:AdminTypeだとtns:id-valueとtns:auth-levelの組み合わせになります。
  • それをxmlではabc:AdminTypeを選んでabc:id-valueとabc:auth-level
i.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="https://dx.ichiri.biz/schema"
           xmlns:tns="https://dx.ichiri.biz/schema"
           elementFormDefault="qualified">

  <xs:complexType name="BaseIdType" abstract="true">
    <xs:sequence>
      <xs:element name="id-value" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="UserType">
    <xs:complexContent>
      <xs:extension base="abc:BaseIdType">
        <xs:sequence>
          <xs:element name="region" type="xs:string"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="AdminType">
    <xs:complexContent>
      <xs:extension base="tns:BaseIdType">
        <xs:sequence>
          <xs:element name="auth-level" type="xs:int"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:element name="ichiri-id" type="tns:BaseIdType"/>

  <xs:element name="ichiri-app-dx">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:ichiri-id"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>
    <abc:id-value>ADM12345</abc:id-value>
    <abc:auth-level>9</abc:auth-level>
  </abc:ichiri-id>

</abc:ichiri-app-dx>
i.xml
<?xml version="1.0" encoding="UTF-8"?>
<abc:ichiri-app-dx xmlns:abc="https://dx.ichiri.biz/schema"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="https://dx.ichiri.biz/schema i.xsd">

  <abc:ichiri-id xsi:type="abc:AdminType">
    <abc:id-value>ADM12345</abc:id-value>
    <abc:auth-level>9</abc:auth-level>
  </abc:ichiri-id>

</abc:ichiri-app-dx>

xs:group

  • これは簡単です。
  • xs:elementをグループ化します。 
  • それをxs:complexTypeにいれて、xs:elementに入れています。
i.xsd
<xs:schema targetNamespace="https://dx.ichiri.biz/schema" 
           xmlns:tns="https://dx.ichiri.biz/schema"
           elementFormDefault="qualified">

  <xs:group name="IdGroup">
    <xs:sequence>
      <xs:element name="id-value" type="xs:string"/>
    </xs:sequence>
  </xs:group>

  <xs:group name="RegionGroup">
    <xs:sequence>
      <xs:element name="region-code" type="xs:string"/>
      <xs:element name="country" type="xs:string"/>
    </xs:sequence>
  </xs:group>

  <xs:complexType name="CombinedUserType">
    <xs:sequence>
      <xs:group ref="tns:IdGroup"/>
      <xs:group ref="tns:RegionGroup"/>
      <xs:element name="email" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="ichiri-app-dx" type="tns:CombinedUserType"/>
</xs:schema>
i.xml
<?xml version="1.0" encoding="UTF-8"?>
<abc:ichiri-app-dx xmlns:abc="https://dx.ichiri.biz/schema"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="https://dx.ichiri.biz/schema i.xsd">

  <abc:id-value>USER-12345678</abc:id-value>

  <abc:region-code>TYO-01</abc:region-code>
  <abc:country>Japan</abc:country>

  <abc:email>ichiri@example.biz</abc:email>

</abc:ichiri-app-dx>
  • xs:sequenceの代わりに、xs:choiceやxs:allも使えます。
  • xs:allは、順不同ですが全て1回使わないといけません。
  • xs:sequenceは、順番を守って全て1回使わないといけません。
  • xs:choiceは、その中から1個だけ使えます。
i.xsd
<xs:schema targetNamespace="https://dx.ichiri.biz/schema" 
           xmlns:tns="https://dx.ichiri.biz/schema"
           elementFormDefault="qualified">

  <xs:group name="AuthChoiceGroup">
    <xs:choice>
      <xs:element name="password-id" type="xs:string"/>
      <xs:element name="biometric-id" type="xs:string"/>
      <xs:element name="token-id" type="xs:string"/>
    </xs:choice>
  </xs:group>

  <xs:group name="SystemInfoAllGroup">
    <xs:all>
      <xs:element name="app-version" type="xs:string"/>
      <xs:element name="db-instance" type="xs:string"/>
      <xs:element name="region-code" type="xs:string"/>
    </xs:all>
  </xs:group>

  <xs:complexType name="IchiriConfigType">
    <xs:sequence>
      <xs:group ref="tns:AuthChoiceGroup"/>     <xs:group ref="tns:SystemInfoAllGroup"/> </xs:sequence>
  </xs:complexType>

  <xs:element name="ichiri-app-dx" type="tns:IchiriConfigType"/>

</xs:schema>

お疲れ様です。 これで完了です。

xsd (XMLスキーマ)Reference

XML Schema Reference
Free HTML XHTML CSS JavaScript DHTML XML DOM XSL XSLT RSS AJAX html ADO PHP SQL tutorials, references, examples for web ...

コメント