連載

.NETで簡単XML

第3回 XML文書を読み書きするプログラムの作成

株式会社ピーデー 川俣 晶
2003/04/08

Page1 Page2 Page3 Page4 Page5

XmlValidatingReaderクラスとXmlTextReaderクラス

 XmlTextReaderクラスは便利なのだが、実はXML文書を処理するという観点からは問題がある。例えば、以下のサンプル・プログラムを見ていただきたい。Windowsアプリケーションのテンプレートでプロジェクト作成後に次のようなコードを書き加えたものである。

 以下は追加するImportsステートメント(C#ではusingディレクティブ)である。

Imports System.IO
Imports System.Xml
VB.NET版のサンプルに必要なImportsステートメント
C#版のサンプルに必要なusingディレクティブ

 以下は書き加える文字列定数とフォームのLoadメソッドの内容である。

Private Const target As String = "<?xml version='1.0' ?>" _
  & "<!DOCTYPE a [ <!ENTITY ent 'ok'> ]>" _
  & "<a>&ent;</a>"

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Dim reader As XmlTextReader = New XmlTextReader(New StringReader(target))
  While reader.Read()
    Trace.WriteLine("ノードを発見: " + reader.NodeType.ToString())
    If reader.NodeType = XmlNodeType.Text Then
      Trace.WriteLine(reader.Value)
    End If
    If reader.NodeType = XmlNodeType.EntityReference Then
      Trace.WriteLine(reader.Name)
    End If
  End While
End Sub
追加する文字列定数とフォームのLoadメソッドの内容(VB.NET版)
追加する文字列定数とフォームのLoadメソッドの内容(C#版)

 これを実行すると、Visual Studio .NETの出力ウィンドウに以下のような内容が出力される。

ノードを発見: XmlDeclaration
ノードを発見: DocumentType
ノードを発見: Element
ノードを発見: EntityReference
ent
ノードを発見: EndElement
出力ウィンドウに表示される内容

 プログラムの内容を簡単にいえば、文字列定数targetの内容をXML文書としてXmlTextReaderクラスで読み込む機能を記述している。ここでは、第1回目では説明していないXMLの機能である「実体(entity)」を使用している。これは一種のマクロであり、あらかじめ定義しておいた文字列と文書中の文字列を置き換える機能を持っている。つまり、「ent」という名前の実体は「ok」という文字列であると定義しておき、「&ent;」と記述したら、それは「ok」という文字列に置き換えて利用するというものである。しかし、出力を見ると分かる通り、「EntityReference」つまり実体を参照するノードを発見しただけで、「ok」という文字列は発見できていない。これでは使い勝手がよくない。

 これを解決するために、XmlTextReaderクラスとは別に用意されているXmlValidatingReaderクラスを使用することができる。XmlValidatingReaderクラスは、XmlTextReaderクラスと同じくXmlReaderクラスを継承している。そのため、XmlValidatingReaderクラスとXmlTextReaderクラスは多くのメソッドやプロパティが共通していて、同じように使用できる。しかし、同じような目的のクラスというわけではなく、XmlValidatingReaderクラスには、スキーマを用いて文書の妥当性を検証するという明確な役割が存在する。つまり、妥当性を検証しながらXML文書を読み取るのが主要な用途であるといえる。では逆に、妥当性を検証しないでXML文書を読み取るのがXmlTextReaderクラスの役割なのかというと、そうでもない。XML1.0勧告では、妥当性を検証しない場合でも、内部実体を展開することを要求している。これを満たすには、XmlValidatingReaderクラスを妥当性検証抜きのモードで使う必要がある。

 具体的にこれを実現するには、以下のようにソース・コードを書き換える。以下は、フォームのLoadイベントの内容を書き換えたものである。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Dim reader As XmlValidatingReader = New XmlValidatingReader( _
    New XmlTextReader(New StringReader(target)))
  reader.ValidationType = ValidationType.None
  While reader.Read()
    Trace.WriteLine("ノードを発見: " + reader.NodeType.ToString())
    If reader.NodeType = XmlNodeType.Text Then
      Trace.WriteLine(reader.Value)
    End If
    If reader.NodeType = XmlNodeType.EntityReference Then
      Trace.WriteLine(reader.Name)
    End If
  End While

End Sub
XmlValidatingReaderクラスを使用するサンプル(VB.NET版)
XmlValidatingReaderクラスを使用するサンプル(C#版)

 これを実行すると以下のような結果になる。

ノードを発見: XmlDeclaration
ノードを発見: DocumentType
ノードを発見: Element
ノードを発見: Text
ok
ノードを発見: EndElement
出力ウィンドウに表示される内容

 このように、「EntityReference」つまり実体を参照するノードを発見することはなくなり、その代わりに「Text」つまりテキストを参照するノードを発見している。その内容も、実体を展開した内容となっている。

 なお、.NET Frameworkのドキュメントによると、OASIS(Organization for the Advancement of Structured Information Standards)が提供するXMLの適合テストにパスする形で利用するには、XmlTextReaderおよびXmlValidatingReaderの設定を、次の例外を除いて既定(デフォルト)の設定にする必要があるとしている。

  • XmlTextReaderでNormalizationプロパティをtrueに設定する(既定値はfalse)。
  • XmlValidatingReaderでValidationCallbackハンドラを割り当る(既定では例外をスローする)。
  • XmlValidatingReaderのValidationTypeプロパティをValidationType.DTDに設定する(既定はValidationType Auto)。

 完全にXML1.0勧告を満たす形でXmlReaderを使うには、以上のような情報にも注意を払う必要がある。


 INDEX
  .NETで簡単XML
  第3回 XML文書を読み書きするプログラムの作成
    1.XML文書を読み込む
    2.XML文書を読み込むサンプル・プログラム
  3.文書の妥当性を検証するXmlValidatingReaderクラス
    4.XML文書を読み書きするサンプル
    5.XML文書を読み書きするサンプルの解説
  
インデックス・ページヘ  「連載 :.NETで簡単XML」

TechTargetジャパン

Insider.NET フォーラム 新着記事
  • Kinectが切り開く“夢の近未来” (2012/2/2)
     日本を含めた世界中でKinect for Windowsセンサー商用版とSDK正式版がリリース。未来のコンピューティングはどう変化するのか?
  • 3つの視点でネイティブと.NETの適材適所を考察 (2012/1/31)
     アプリ開発は「ネイティブ」と「.NET」、どちらが最良? その問いには「適材適所」と答えるしかない。では、“適所”は一体どこかを考察する
  • SQL Azure Data Sync入門 (2012/1/30)
     SQL Azure/SQL Serverデータベース間のデータ同期を簡単に実現するサービスとは? その仕組みや使用手順を解説
  • Windows Phoneアプリ市場の現状を分析する (2012/1/27)
     Windows Phone のアプリ・ストアに日々登録されている多種多様なアプリ。カテゴリ別のアプリ数は? 市場の現状を明らかにする

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

- PR -
@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH