制約ファセット(3) - 正規表現によるパターン

2002年7月28日(日)更新


■制約ファセット: 郵便番号の例

たけち: 今回が制約ファセットの一番最後だよ。

さらら: うっ、うん・・・・

たけち: さらら、どうしたの?

さらら: だって前回の終わりにたけちが「とても難しい制約ファセット」っていうから、わかるかしら、と思って・・・・・

たけち: そんなに心配しないで。確かに今日の話はきちんと覚えようと思ったら大変で、真面目に勉強しだすと1回では絶対終わらない内容なんだよね。そのためにここで本格的に勉強しだすと、いつまで経っても複合型の勉強なんかには入れない。だから今は覚えずに「こんなこともできるんだ」程度にさらっと見てくれればいいよ。必要になった時に、ちゃんとした本できちんと勉強すればいいからね。

さらら: じゃあ、さらっと見せてね(^ ^;

たけち: うん。じゃあもっとも月並みな例だけれど、まず日本の郵便番号から考えよう。たとえば、次のようなXMLデータがあるとするね。

さらら

<?xml version="1.0" encoding="Shift_JIS" ?>
<jpc>680-0841</jpc>

たけち: 日本の郵便番号は、680-0841 みたいに、まず3桁の数字があって、それからハイフンがあり、そして次に4桁の数字があるよね。こういう形式はいままでの制約ファセットでは表現できなかったよね。

さらら: そうだわね。こういう形式はとても定義できないわよね。

たけち: うん。でも、実際には次のようにすると、郵便番号のようなデータ型が定義できるんだよ。

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="jpc" type="JapanesePostalCodeType" />

<xsd:simpleType name="JapanesePostalCodeType">
<xsd:restriction base="xsd:string">
  <xsd:pattern value="\d{3}-\d{4}" />
</xsd:restriction>
</xsd:simpleType>

</xsd:schema>

さらら: <xsd:pattern value="\d{3}-\d{4}" />って何なの? patternというのは、なんとなく意味がわかるけれど、"\d{3}-\d{4}"っていうのがわけがわからないわ。

たけち: まず\dというのは数字を意味しているんだよ。そしてその後に{3}が付くということは、「数字が3つ(3桁)」という意味だし、-(ハイフン)の後の{4}は数字が4つという意味だね。これにより結果的に、「数字3桁 -(ハイフン) 数字4桁」という結果になるんだよ。

さらら: ちょっと面倒くさそうね。


■日本の元号のデータ型の例

たけち: これはまだ簡単な方だよ。そういえば以前、さららは日本の元号のデータ型がないことを悩んでいたよね。

さらら: ぎくっ、そ、そうだったかしら(^^;

たけち: 例えば、「平成12年3月31日」とか「天平宝字元年12月5日」などを表すデータ型を作ってみようね。次のスキーマを見て。

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="jdate" type="JapaneseDateType" />

<xsd:simpleType name="JapaneseDateType">
<xsd:restriction base="xsd:string">
  <xsd:pattern value="[\p{IsCJKUnifiedIdeographs}]+([1-9][0-9]|[2-9]|元)年(1[0-2]|[1-9])月(3[01]|[12][0-9]|[1-9])日" />
</xsd:restriction>
</xsd:simpleType>

</xsd:schema>

※簡単のために、閏月(うるうづき)のある太陽太陰暦ではなくて現代の太陽暦としています。また、年号は1年を元年とし、正月は1月などとしています。

さらら: えっ〜と、xsd:patternという要素の中のvalue属性の値が
[\p{IsCJKUnifiedIdeographs}]+([1-9][0-9]|[2-9]|元)年(1[0-2]|[1-9])月(3[01]|[12][0-9]|[1-9])日
となってるけど、これってな〜に?

たけち: ぱっと見たらわけのわからない数字と記号の羅列だけど、一つずつ見ていったら、それほど難しくはないんだ。
まず元号は最初に、「平成」とか「天平宝字(てんぴょうほうじ)」は漢字2文字か4文字から成り立っているよね。XMLではUnicodeが基本になっていて、そのUnicodeでは漢字は「CJK Unified Ideographs」というんだ。CはChina、JはJapan、KはKoreaで「中国・日本・韓国 統合漢字」という意味だね。
そして[]という記号は、[]で囲まれた中であらわされた文字のうち1文字を意味しているんだ。
この結果、[\p{IsCJKUnifiedIdeographs}]と書くことで、Unicodeで表現される漢字一文字をあらわしているんだ。

たけち

xsd:patternのvalue属性

さらら: それで、その次の + は加えるという意味なの?

たけち: これはね、DTDを勉強したときに、

  • +  1以上
  • ?  0か1
  • *  0以上
  • |  または

たけち:  ということを勉強したよね。この+はそれと同じ意味で、ここでは「漢字が一文字以上」ということを意味しているんだよ。

さらら: なるほど、DTDの真似をしているのね。

たけち: えっ〜と (^ ^; DTDの真似をしたんじゃなくて、まず正規表現というものがこういうふうに定めていて、それをDTDや<xsd:pattern>が採用したというわけなんだけどね。

さらら: そうなのね。じゃあ次の ([1-9][0-9]|[2-9]|元)年 というのは何なの?

たけち

たけち: まず元号は100年を越えることは普通考えられないよね。だから1桁または2桁の数ということになるんだ。2桁の数を[1-9][0-9]であらわしているんだよ。
先ほども説明したように[ ]は、その中で候補となる文字のうち1文字を意味しているよね。だから[1-9]と書くことによって、1〜9までの文字のうち1文字という意味になるし、[0-9]で0〜9までの文字のうち1文字を意味しているんだ。結果的にこれは2桁目が1〜9、1桁目が0〜9という数を意味することになるよね。これで10〜99の数が表現できるんだ。

xsd:patternのvalue属性(2)

さらら: あら、[0-9][0-9]じゃないの?

たけち: それだと、「03」という書き方が許されてしまうよね。もちろんそういう書き方でも良いというふうに決めたならそれでいいのだけれど、ここではやめておこうね。
それで1桁の数の場合が、次の[2-9]になるんだ。これは2〜9までという意味だよ。さっきも言ったように | が、またはの意味になるから、「[1-9][0-9]|[2-9]」という書き方で、2〜99の数が表現できるよね。

さらら: 1はないの?

たけち: 元号の場合「1年」と言わずに元年と言うでしょ。

さらら: あ、そうか (^ ^;

さらら

たけち: というわけで、まとめると、「([1-9][0-9]|[2-9]|元)年」と書くことによって、「13年」とか「6年」とか「元年」という表記ができるわけなんだ。

さらら: やっとわかったわ。。。。。あ、すると (1[0-2]|[1-9])月 というのも、なんとなくわかるわ。

たけち: そう、月は1月〜12月までだから、1〜9月の1桁の場合と、10,11,12月の2桁の場合を考えればいい。この場合、1[0-2]という書き方で、10,11,12をあらわしているんだよ。

さらら: (3[01]|[12][0-9]|[1-9])日 というのがよくわからないけれど、これは?

たけち: これは1〜31日を表しているのだけれど、まず、30,31を3[01]として表しているんだ。[01]は0か1かという意味だね。次に10〜29を[12][0-9]として表しているんだ。[12]は1か2かという意味だね。

xsd:patternのvalue属性(3)

さらら: なるほど、わかったわ。それでこれ全部で「平成12年3月31日」とか「天平宝字元年12月5日」といった元号が表現できるのね。なかなか面倒だけれど確かに細かく決められるわね。

元号の例まとめ

たけち: そうだね。正規表現はもっと奥が深くて、勉強しないといけないことがもっとあるんだけれど…

さらら: これはもういいわ (^ ^;  正規表現はまた余裕のあるときに教えてね。

たけち: それじゃあ、今回は、ひとまずこれでおしまい (^ ^;

さらら: ありがと。

→ 次回はユニオン(union)データ派生型です。。。。。 (^ ^)v

たけち


XMLスキーマのコーナーは、TAKABEさま(XSLTの遊び部屋)の全面的なご協力をいただいて作成しています。