- PR -

空になるかもしれない要素

1
投稿者投稿内容
momo
常連さん
会議室デビュー日: 2006/11/06
投稿数: 35
投稿日時: 2007-10-03 21:25
javaでXMLを読み込みDBにデータを取り込み、
DBから取ってきたデータでXMLを作成して送信するものを作成しています。

データベースに値がないものは空要素としてXMLを作成してほしいと
お客さんから要望があります。(お客さん側はC#)
XSDは現在こちらで作成しています。

作成したXSDでXMLの検証を行っていみると、空タグで

cvc-pattern-valid: Value '' is not facet-valid with respect to pattern '\d{1,13}' for type 'Identifier_Num_Max13'.

のようなエラーが出ます。
空タグのXSDにおける宣言は型付です。

調べてみると、XSDの要素の宣言のところに

nillable="true"

を記述し、空要素のほうに

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"

を記述するようにとありました。
が、空になるかもしれない要素はXML文書の8割ほどを占めるので、
いちいちからタグに上記のものを記述するのは億劫です。
見づらいですし。
ほかに空かもしれない要素を許す方法はないでしょうか。

やはり要素に値が入らない任意のタグは、
値がない場合はタグそのものをXMLに記述しないような
仕様のほうがいいのでしょうか。
かめたろ
ぬし
会議室デビュー日: 2003/03/20
投稿数: 255
投稿日時: 2007-10-05 17:31
お客さんに、なんでそういうことを言うのか聞いてみたほうがいいかもしれません。

引用:

データベースに値がないものは空要素としてXMLを作成してほしいと
お客さんから要望があります。(お客さん側はC#)


NULL値と空文字列を区別しないということでしょうか?
空要素を文字型以外の型で表現するのはムリだと思います。
お客さんがどうしても空要素じゃなきゃやだって言うなら、全ての要素の型をstring型にするしかないのではないでしょうか。
空要素を送るかどうかは別にして、全ての要素の型をstring型にするってケースは実際ありました。

string型の場合。
XSD上はNULL不可(minOccurs="1")となっているところに要素無しのXMLを送りつけた場合、その要素は空文字列に変換されたような記憶があります。(つまり空要素のXMLと同じ)
int型などの場合。
XSD上はNULL不可(minOccurs="1")となっているところに要素無しのXMLを送りつけた場合、検証エラーとなった記憶があります。
#この部分、自信はありません。

引用:

調べてみると、XSDの要素の宣言のところに
nillable="true"
を記述し、空要素のほうに
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"
を記述するようにとありました。


こちらが参考になるかもしれません。
XML Schemaでのヌルの表現(IBM)
nillable="true"の他に、minOccurs="0"、属性の場合はuse="optional"があります。
今までのところminOccurs="0"で充分だったので、nillableは使ったことありません。

引用:

やはり要素に値が入らない任意のタグは、
値がない場合はタグそのものをXMLに記述しないような
仕様のほうがいいのでしょうか。


それが一般的だと思います。

なんか纏まりませんでした・・・。
参考になれば幸いです。

[ メッセージ編集済み 編集者: かめたろ 編集日時 2007-10-05 17:43 ]
momo
常連さん
会議室デビュー日: 2006/11/06
投稿数: 35
投稿日時: 2007-10-10 17:49
引用:
お客さんに、なんでそういうことを言うのか聞いてみたほうがいいかもしれません。



推測ですが、仕様を決める人がXMLの知識があまりない方だからかなと。
こちらもそういうメンバがいないので、いつのまにか任意のタグは数値型であれなんであれ
空要素を許すという仕様で落ち着いてしまいました。
スケジュール的にももう後戻りもできず・・。
だけれどもXMLスキーマを作っていざバリデーションをかけると、数値型などの空要素でエラーと
なってしまい途方にくれていました。

文字列の場合はxsd:minLength value="0"にすることで、空要素でも検証に
引っかからなくなったのですが、元の型がintなどの数値だと、XMLで空要素の
ときに要素の宣言がminOccurs= 0でもヴァリデーションにひっかかってしまい・・・。


引用:
NULL値と空文字列を区別しないということでしょうか?



そうですね、区別しません。
こちらはもらったデータを対応するDBの項目に入れているだけなのです。
DBはOracleなので文字列は空文字'' = nullになりますし、数値項目も空要素の場合はnull(DB側はNumber)を入れます。
さらに値が数値かどうかをXMLスキーマで検証したいけれども空要素も許すといった仕様です。

引用:
お客さんがどうしても空要素じゃなきゃやだって言うなら、全ての要素の型をstring型にするしかないのではないでしょうか。



それが、数値かどうかの検証をしたいけれども空要素OKという要望があり、数値の検証もできてかつ空OKとできないかと思案していました。


そこで色々調べていたらこういうTipsがありました。

XML Schemaでnull値の許容を定義する
http://www.atmarkit.co.jp/fxml/tecs/038xsd/38.html


上記サイトを参考に、こんな型を宣言することで逃げることにしました。
(元の型はNumeric_10を指定して、空要素でエラーになっていました。)
コード:
<!-- ヌル型 -->
<xsd:simpleType name="nullable">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="" />
  </xsd:restriction>
</xsd:simpleType>
<!-- ベース型 -->
<xsd:simpleType name="Numeric_10">
  <xsd:restriction base="xsd:nonNegativeInteger">
    <xsd:totalDigits value="10" />
    <xsd:fractionDigits value="0" />
    <xsd:pattern value="\d*" />
  </xsd:restriction>
</xsd:simpleType>
<!-- ヌル型 + ベース型 -->
<xsd:simpleType name="Null_Numeric10">
  <xsd:union>
    <xsd:simpleType>
      <xsd:restriction base="xxx:nullable" />
    </xsd:simpleType>
    <xsd:simpleType>
      <xsd:restriction base="xxx:Numeric_10" />
    </xsd:simpleType>
  </xsd:union>
</xsd:simpleType>

<!-- 要素宣言 --> 
<xsd:element minOccurs="0" maxOccurs="1" name="taxMoney" type="xxx:Null_Numeric10" />



これから似たような状況に置かれたときはどうどうと
「空要素になる場合は要素自体を作らないのが普通」
を主張していきたいと思います。
かめたろ
ぬし
会議室デビュー日: 2003/03/20
投稿数: 255
投稿日時: 2007-10-11 14:53
おおー、なるほどぉ。unionを使えば表現できますね。
全く思いつかなかったので勉強になりました。フィードバックありがとうございます。

引用:

DBはOracleなので文字列は空文字'' = nullになりますし、数値項目も空要素の場合はnull(DB側はNumber)を入れます。


これは、アプリケーションかDBで何らかの細工をしてますよね?
Oracleに限らず、文字型のフィールドに '' をupdateすると、普通は '' が更新されるはずで null にはなりませんよね。

引用:

「空要素になる場合は要素自体を作らないのが普通」
を主張していきたいと思います。


私的には、
・NULLの場合は、要素自体つくらない(またはnil)
・''(空文字)の場合は、要素はつくる
・string以外の型に innerText='' はありえない
こんなかんじかなと思っています。
#空文字とNULL値は別モノ!
但し、今回のようにケースバイケースな部分もあるでしょうね。

私もXMLで受け取った内容をDBに更新したりしてます。
NULLを意識して活用する例としては、例えばXMLには変更点のみ含まれていて、それをDBに反映する場合、NULLのフィールドはDB更新せず値の入っているフィールドのみ更新するっていう制御が可能となります。
momo
常連さん
会議室デビュー日: 2006/11/06
投稿数: 35
投稿日時: 2007-10-17 09:54

引用:
Oracleに限らず、文字型のフィールドに '' をupdateすると、普通は '' が更新されるはずで null にはなりませんよね。



それが、残念ながらOracleは可変長文字列(VARCHAR2とか)のフィールドに
''をUPDATEしてもnullのままなのです・・・。
なのでNotNull制約の可変長文字列フィールドに''をUPDATEすると怒られます。
もちろん''でUPDATEした項目をSELECTしてもnullで返ってくるんです。

引用:
私的には、
・NULLの場合は、要素自体つくらない(またはnil)
・''(空文字)の場合は、要素はつくる
・string以外の型に innerText='' はありえない
こんなかんじかなと思っています。
#空文字とNULL値は別モノ!



これからの参考にさせていただきたいと思います。
ありがとうございました。


かめたろ
ぬし
会議室デビュー日: 2003/03/20
投稿数: 255
投稿日時: 2007-10-17 11:05
引用:

それが、残念ながらOracleは可変長文字列(VARCHAR2とか)のフィールドに
''をUPDATEしてもnullのままなのです・・・。
なのでNotNull制約の可変長文字列フィールドに''をUPDATEすると怒られます。
もちろん''でUPDATEした項目をSELECTしてもnullで返ってくるんです。


ありゃ、そうなんですか・・・。
ぅぅ、恥ずかしいなぁ。無知な上に私には思い込みがあったようです。
失礼しました。
1

スキルアップ/キャリアアップ(JOB@IT)