まー、XML-DTDの#PCDATAという記法/概念は、まったく使い物にならないシロモノなんだよね。代替として1文字を表す#charを出したけど、もう1つの代替として#dataという記号を導入しましょう。#dataは、内容に含まれる極大な文字列とマッチします(DOMのノード正規化後のテキストノードと同じ)。
事前に空白処理を済ませておけば、#dataが空(長さ0)の文字列とマッチすることはありません(空白文字を含む文字列とマッチする可能性はある)。極大であることから、(#data, #data)、(#data)+、(#data)* のような表現は使えません。でも、(#data)? はOKです。
さらに、#data(type)で型付けされた文字列(simple typeのデータですね)とマッチすると約束すれば、priceの例(最初に出した例)の内容構文モデルは:
と書けますね。ちなみに、unitの内容構文モデルは (#data(currency))です。
(#data(nonNegativeInteger), unit)
「価格の数値と単位のあいだを区切り記号<sep/>で区切り、単位がないときは円と解釈するから省略可能」という(けっこう変な)規則でも次のように記述できます。
(#data(nonNegativeInteger), (sep, #data(currency))?)
この内容構文モデルに対してprice要素がvalidなら、レコード構造との次のマッピング(の安全性)が保証されます。
- 1番目の子ノード(テキストノード)→ フィールドvalueの値
- 3番目の子ノード(テキストノード)→ フィールドunitの値
- 3番目の子ノードがない → フィールドunit = null
(続く)