C# TIPS:XML ファイルからスキーマを生成

XML Schema は難しいと感じるのは自分だけであろうか。1から手書きなど絶対に無理。はじめにXMLファイルがあればそれを元に XML Schema を作ってくれないかなー、と思っていた。


Visual Studio 2005 には、コードスニペット という機能があり、よく使うコード類があらかじめ登録されている。ソースコード上で右クリック → スニペットの挿入。


実はこれ、C# にはほとんどスニペットが用意されておらず、VB.NETにはかなりの数のスニペットが用意されている。VB.NET を日常使わないのでその事実に気づかなかった。そこであらかじめ登録されているスニペットをつらつらと眺めながらほほー、こんな書き方があるのか、など感心しながら見ていたらこんなのを見つけた。

         ↓

XML ファイルからスキーマを生成する!スニペットを選択するとこのようなコードを書いてくれます。

    Imports System.IO
    Imports System.Xml
    Imports System.Xml.Schema
        ' Gets the schema.
        Dim infer As New XmlSchemaInference()
        Dim sc As New XmlSchemaSet()
        sc = infer.InferSchema(New XmlTextReader("sample.xml"))

        ' Writes the schema.
        Dim w As XmlWriter = XmlWriter.Create(New StreamWriter("sampleSchema.xsd"))
        Dim schema As XmlSchema
        For Each schema In sc.Schemas()
            schema.Write(w)
        Next schema

XmlSchemaInference クラスというのが XML ファイルから スキーマを類推してくれます。賢い。

これを参考にC#で書いてみた。XMLファイルは
http://msdn2.microsoft.com/en-us/library/ms762271.aspx
にあるXMLを使用する。それを C:\temp\books.xml として保存しておく。
Visual Studio で新規作成 → プロジェクト でC#のコンソールアプリケーションを作成する。

先頭に

using System.Xml;
using System.IO;
using System.Xml.Schema;

Mainの中に

            XmlSchemaInference scInfo = new XmlSchemaInference();
            XmlSchemaSet sc = new XmlSchemaSet();
            sc = scInfo.InferSchema(new XmlTextReader(@"C:\temp\books.xml"));
            XmlWriter w = XmlWriter.Create(@"C:\temp\books.xsd");
            foreach (XmlSchema schema in sc.Schemas())
            {
                schema.Write(w);
            }

と書く。実行するとC:\temp\books.xsd とファイルができて、中身は以下の通り。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="catalog">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="author" type="xs:string" />
<xs:element name="title" type="xs:string" />
<xs:element name="genre" type="xs:string" />
<xs:element name="price" type="xs:decimal" />
<xs:element name="publish_date" type="xs:date" />
<xs:element name="description" type="xs:string" />
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

実際には改行していないのですが見やすさのために改行しました。

このように、コードスニペットは自分の思いつかなかったコードが眠っている宝箱みたいなものなのでじっくりと探索してみてはいかがでしょうか。今回のXMLファイルからスキーマ生成というのもほぼあきらめていたことなのでこんなに簡単にできてびっくりです。

もちろん、本来なら最初にちゃんとスキーマ設計しろよ、ということになるのでしょうが、こんなお手軽なやり方もあるよ、ということで。
あ、お手軽度合いでいうと xsd コマンドを使う方法もありますね。。Visual Studio コマンドプロンプトから

xsd books.xml

を実行すれば books.xsd ができるではないか。。時と場合により使い分けよう。


参考ページ
どう書くんだっけ? を「コード・スニペット」で一発挿入! - @IT
http://msdn2.microsoft.com/ja-jp/library/x6c1kb0s(VS.80).aspx
http://msdn2.microsoft.com/ja-jp/library/system.xml.schema.xmlschemainference.xmlschemainference(VS.80).aspx