InfoPath 2010 で添付ファイルを削除した際にInfoPath 2003/2007 でフォームを開くとエラーが表示される現象について

こんにちは InfoPath サポートの森 健吾 (kenmori) です。

社内事情により、本ブログ オーナーである柴田、森は職務内容が変更となりました。本ブログに関連する製品としては、引き続き InfoPath, Project, Groove を含むクライアント製品をサポートします。その他の主要な Office 製品に関する投稿は、別途著者を募集しております。

今回の投稿では InfoPath に関連する情報を投稿してみます。
InfoPath 2003/2007から InfoPath 2010 移行のバージョンにアップグレードする際に、ネットワーク上にある様々なクライアント端末において、2003, 2007, 2010 などが混在する際に生じる互換性の制限事項を取り上げます。この問題に対応する中で、Microsoft Script Editor の使用方法等をお伝えします。

シナリオ

InfoPath 2003 または 2007 クライアント互換のフォーム テンプレートを作成します。
このフォーム テンプレートから生成されるフォームを InfoPath 2010 で添付ファイル データを削除して XML ファイルを保存した場合、InfoPath 2003 や 2007 で同じ添付ファイルのデータが入力規則エラーと認識されてしまいます。

 

再現手順

1. InfoPath 2003 または 2007 クライアント互換のフォーム テンプレートに添付ファイル フィールドを追加して発行します。

 
 
2. 発行したフォーム テンプレートをもとに InfoPath 2010 でフォームを開きます。
3. 添付ファイルを追加した後、すぐに削除します。
4. XML フォームを保存します (エラーがないことを確認します。)。
5. 同じ XML フォームを InfoPath 2003 または InfoPath 2007 で開きます。

この状況の場合、動作規則などで、フォームを送信することができません。

 

原因

本動作は、InfoPath 2010 以降が使用する MSXML6.DLL における動作変更に起因します。
添付ファイル フィールドを空に設定した場合、InfoPath 2003, 2007 と InfoPath 2010 ではそれぞれ以下のように保存されます。

 

InfoPath 2003, 2007

<my:Attachment xsi:nil="true"></my:Attachment>

InfoPath 2010

<my:Attachment></my:Attachment>

 

InfoPath 2010 では MSXML5.dll に対するサポートを打ち切り、MSXML6.dll を使用するよう変更されました。
InfoPath は、添付ファイル フィールドを Base64Binary 型として実装しており、MSXML6.dll において nil 属性の指定なしに空のデータを許容するよう動作変更されたため、結果として上述のような XML の相違が生じる結果となりました。

- 補足
InfoPath の添付ファイルやイメージ フィールドは、Base64Binary 型として定義されます。

<xsd:element name="Attachment" nillable="true" type="xsd:base64Binary"/>

 

動作変更の経緯と詳細

W3C XML Schema では、Base64Binary データ型のスキーマ定義において、nil 属性を指定せずに空のデータを保持できるよう定義されています。

<MSXML の動作変更>
MSXML5.dll までは、Base64Binary 型の値が空である場合、nil 属性がない場合は構文エラーとするよう定義しておりました。
MSXML6.dll では、標準のスキーマ定義に準拠する形で、内部のスキーマ定義が見直され nil 属性なしの空データを許容する設計となりました。
このため、MSXML6 では、スキーマ検証を行った場合の条件が緩和されている結果となっております。

<InfoPath の動作 (変更なし)>
InfoPath の XML ノードを更新する際の全般的な実装として、値を設定したあとに MSXML パーサーからエラーが返された場合に、該当ノードの定義が nillable であり、設定しようとしている値が空であれば、nil 属性 (xsi:nil=”true”) を追加するように実装されております。
この部分の実装は、InfoPath 2003、InfoPath 2007、InfoPath 2010 において変更はありません。

しかし、上記 MSXML がエラーを返すかどうかで動作が分かれてしまう状況です。Microsoft 製品としては W3C 標準に準拠するための MSXML の動作変更と逆の方向性となる対処策を製品に組み込みにくいという判断です。

 

参考情報

InfoPath 2010 において、MSXML6 を使用するよう変更された記述は以下に記載がありますので、ご確認ください。

タイトル : InfoPath 2010 での変更点
アドレス : https://technet.microsoft.com/ja-jp/library/cc179229(v=office.14).aspx

-- 抜粋 開始 --
Office 2010 は、Microsoft XML パーサー バージョン 5 (MSXML5) をサポートしていません。既存のソリューションでは、Office 2010 によって MSXML5 オブジェクトを読み込んでもインスタンスは作成されません。Microsoft .NET Framework を使用して、コードをマネージ コードに移行します。また、MSXML6 に移行するという方法もあります。ただし、MSXML6 は、デジタル署名コードをサポートしていないことに注意してください。
-- 抜粋 終了 --

InfoPath XML データソースを直接操作する場合、nil 属性を考慮したコーディングを行う必要があります。

タイトル : [方法] XPathNavigator クラスおよび XPathNodeIterator クラスを操作する方法
アドレス : https://msdn.microsoft.com/ja-jp/library/office/aa945227(v=office.14).aspx
参考箇所 : xsi:nil 属性を持つノードの値を設定する

InfoPath 2010 の公開情報に nil 属性を指定するデータ型一覧に  Base64Binary 型が記載されていないことが確認できます。

-- 抜粋 開始 --
InfoPath は、次のデータ型の Null フィールドについては xsi:nil 属性を true に設定します。
・Whole Number (integer)
・Decimal (double)
・Date (date)
・Time (time)
・Date and Time (dateTime)
-- 抜粋 終了 -- 

 

対処策

Microsoft Script Editor を使用した JScript によるカスタマイズにより、添付ファイル コントロールでファイルを削除した際に xsi:nil 属性をセットします。

1. 呼び出し先の関数を定義します。

1) InfoPath フォーム テンプレートをデザイン モードで開きます。

2) メニュー バーより [ツール] - [フォームのオプション] をクリックします。

3) "カテゴリ" より [プログラミング] を選択します。

4) "フォーム テンプレートのコード言語" より "JScript" を選択します。

  補足

   ブラウザ互換フォームを作成する場合は、スクリプト (JScript, VBScript) をご利用いただけません。

5) [OK] をクリックします。

6) メニュー バーより [ツール] - [プログラミング] - [Microsoft Script Editor] をクリックして、Microsoft Script Editor を起動します。

 

 

7) 以下のような関数を記載ください。

 -- サンプル 開始 --
function setAttrNil(obj)
  {
    if (obj.text == "")
    {
      if (obj.getAttribute("xsi:nil"))
      {
        obj.setAttribute("xsi:nil", "true");
      }
      else
      {
        var xmlNil = XDocument.DOM.createNode(2, "xsi:nil", "https://www.w3.org/2001/XMLSchema-instance");
        xmlNil.text = "true";
        obj.setAttributeNode(xmlNil);
      }
    }
  }
  -- サンプル 終了 -- 

 

2. 添付ファイル フィールドの変更イベントで上記関数を呼び出します。

1) "デザイン タスク" にて、[データ ソース] をクリックします。

2) 添付ファイル コントロールにバインドされたデータ ソースを右クリックし、[プログラミング] - [OnAfterChange イベント] をクリックします。

3) Microsoft Script Editor にてスクリプトが開かれ、コードが自動生成されます。

4) 変更前と変更後の値を考慮して、事前準備にて用意した関数 (setAttrNil 関数) の呼び出しを含む、以下緑のコードを記載します。

  -- サンプル 開始 --
  function msoxd_my_Attachment2::OnAfterChange(eventObj)
  {
       // ここにコードを書き込んで、グローバル状態に戻してください。

       if ((eventObj.OldValue != "") && (eventObj.NewValue == ""))
       {
            setAttrNil(eventObj.Parent);
       }

       if (eventObj.IsUndoRedo)
       {
            // 元に戻すまたはやり直しの操作が発生しましたが、DOM は読み取り専用です。
            return;
       }

   // フィールドが変更されました。DOM は書き込み可能なので、ここにコードを書き込んで、変更に応答してください。
  }
  -- サンプル 終了 --

本対処策は、InfoPath 2010 以降のクライアントに xsi:nil 属性を持たない XML ノードを作成させないことで、InfoPath 2003 や 2007 でエラー検知させることを防止するための対策となります。
従いまして、すでにフォーム ライブラリ上などに保存された xsi:nil 属性を持たない XML ファイルを、InfoPath 2003 と 2007 で開いた際のエラーは解消されません。
このような状況でフォームを修正することをご希望の際は、フォームを開く際に xsi:nil=”true” を含める方法をご検討ください。

注意

Microsoft Script Editor の開発環境は InfoPath Designer 2010 からは削除されておりご利用いただけません。
今回は、InfoPath 2003, 2007 との互換性を保つことを目的のコードとしますので、.NET Framework などの前提条件が不要な Jscript を意図的に選択しています。

現在の時期、Windows XP や Office 2003 サポート終了を前に、バージョンアップ作業等を実施いただいている方もいらっしゃると思います。このような問題が生じたら、ネットワーク上に様々なバージョンの InfoPath クライアントが存在する期間限定の一時的な対処策として上記をお役立ていただけますと幸いです。

今回の投稿は以上になります。