none
using System.Xml のバグ? RRS feed

  • 質問

  • お世話になっております。次のコードを実行すると、XMLの読み込みエラーとなってしまいます。これはSystem.xmlのバグではないでしょうか?ほかの処理系に食わせてもxml is validで正しいと判定されます。

    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Web;
    using System.Net;
    using System.Collections.Specialized;
    using System.IO;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Text;

    namespace XMLLoadTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                string FileURL = "http://disclosure.edinet-fsa.go.jp/taxonomy/jplvh/2013-08-31/jplvh_rt_2013-08-31.xsd";

                DateTime lastModified = DateTime.MinValue;
                if (System.IO.File.Exists(FileURL))
                {
                    return;
                }

                WebClient client = new WebClient();
                string content = client.DownloadString(FileURL);

                //Test for urls that return empty text data
                try
                {
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(content);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }
    }

    実行:

    B:\XMLLoadTest\XMLLoadTest\bin\Debug>XMLLoadTest.exe
    System.Xml.XmlException: 行 32、位置 10 にある開始タグ 'link:definition' と終了タグ 'link:roleType' が対応していません。 行 37、位置 9。
       場所 System.Xml.XmlTextReaderImpl.Throw(Exception e)
       場所 System.Xml.XmlTextReaderImpl.Throw(String res, String[] args)
       場所 System.Xml.XmlTextReaderImpl.ThrowTagMismatch(NodeData startTag)
       場所 System.Xml.XmlTextReaderImpl.ParseEndElement()
       場所 System.Xml.XmlTextReaderImpl.ParseElementContent()
       場所 System.Xml.XmlTextReaderImpl.Read()
       場所 System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
       場所 System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
       場所 System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
       場所 System.Xml.XmlDocument.Load(XmlReader reader)
       場所 System.Xml.XmlDocument.LoadXml(String xml)
       場所 XMLLoadTest.Program.Main(String[] args) 場所 B:\XMLLoadTest\XMLLoadTest\Program.cs:行 43

    ちなみに、.NET 2.0/3.0/4.0すべて同じです。

    2015年10月18日 2:44

回答

  • DownloadStringでエンコードが一致していないので文字化けしてます。
    文字化けしている状態でXML解析しようとしてエラーになってます。

    エンコード指定してDownLoadStringするか、DownloadDataでバイト配列として取り出したものを文字列化せずに渡しましょう。(OpenReadのStreamでもいいです)

    WebClient client = new WebClient();
    client.Encoding = System.Text.Encoding.UTF8;
    string content = client.DownloadString(FileURL);
    
    var bs = client.DownloadData(FileURL);
    System.IO.MemoryStream ms = new MemoryStream(bs);
    try
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(ms);
        //doc.Load(client.OpenRead(FileURL));
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2015年10月18日 3:35
    • 回答としてマーク 星 睦美 2015年10月30日 5:34
    2015年10月18日 3:31
  • 補足します。

    WebClient.DownloadStringメソッド

    このメソッドは、リソースをダウンロードした後、Encodingプロパティに指定されたエンコーディングを使用して、リソースをStringに変換します。

    と説明されています。更にWebClient.Encoding プロパティ

    このプロパティの既定値は、Default によって返されるエンコーディングです。

    と説明されています。ここでEncoding.Defaultは日本語版WindowsであればShift-JISです。しかし実際のコンテンツはUTF-8のようです。

    結局のところ、System.Xmlのバグでもなんでもなく、WebClient.DownloadStringメソッドの使い方誤りです。

    SurferOnWwwさんが書かれているようにXmlDocumentクラスにはダウンロードを行うLoad()メソッドもありますのでこちらを使うべきですが、あえてWebClientクラスを使うのであれば、WebClient.OpenRead()メソッドを用いてStreamを得て、XmlDocument.Load()メソッドにそのStreamを渡すことです。というのもXML仕様にはエンコーディングに関する取り決めもあるため、validなxmlである限り呼び出し側で明示的に指定する必要はありません。


    • 編集済み 佐祐理 2015年10月18日 6:32
    • 回答としてマーク 星 睦美 2015年10月30日 5:34
    2015年10月18日 3:56
  • > 次のコードを実行すると、XMLの読み込みエラーとなってしまいます。
    > これはSystem.xmlのバグではないでしょうか?

    単純に以下のようにして問題ないのでバグではないと思いますが? sample2.xml はブラウザで FileURL の url にアクセスして表示された内容そのままのファイルです。

    XmlDocument document = new XmlDocument();
    document.Load(@"C:\Users\...省略...\ConsoleApplication5\sample2.xml");
    Console.WriteLine(document.OuterXml);

    原因究明には、疑っている部分以外の余計なところをどんどん削除していって試してみることをお勧めします。

    【追伸】

    ファイルから読む代わりに、以下のように直接 URL を指定しても OK でした。

    document.Load("http://disclosure.edinet-fsa.go.jp/taxonomy/jplvh/2013-08-31/jplvh_rt_2013-08-31.xsd");

    • 編集済み SurferOnWww 2015年10月18日 3:46 追伸追加
    • 回答としてマーク 星 睦美 2015年10月30日 5:34
    2015年10月18日 3:37

すべての返信

  • DownloadStringでエンコードが一致していないので文字化けしてます。
    文字化けしている状態でXML解析しようとしてエラーになってます。

    エンコード指定してDownLoadStringするか、DownloadDataでバイト配列として取り出したものを文字列化せずに渡しましょう。(OpenReadのStreamでもいいです)

    WebClient client = new WebClient();
    client.Encoding = System.Text.Encoding.UTF8;
    string content = client.DownloadString(FileURL);
    
    var bs = client.DownloadData(FileURL);
    System.IO.MemoryStream ms = new MemoryStream(bs);
    try
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(ms);
        //doc.Load(client.OpenRead(FileURL));
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2015年10月18日 3:35
    • 回答としてマーク 星 睦美 2015年10月30日 5:34
    2015年10月18日 3:31
  • > 次のコードを実行すると、XMLの読み込みエラーとなってしまいます。
    > これはSystem.xmlのバグではないでしょうか?

    単純に以下のようにして問題ないのでバグではないと思いますが? sample2.xml はブラウザで FileURL の url にアクセスして表示された内容そのままのファイルです。

    XmlDocument document = new XmlDocument();
    document.Load(@"C:\Users\...省略...\ConsoleApplication5\sample2.xml");
    Console.WriteLine(document.OuterXml);

    原因究明には、疑っている部分以外の余計なところをどんどん削除していって試してみることをお勧めします。

    【追伸】

    ファイルから読む代わりに、以下のように直接 URL を指定しても OK でした。

    document.Load("http://disclosure.edinet-fsa.go.jp/taxonomy/jplvh/2013-08-31/jplvh_rt_2013-08-31.xsd");

    • 編集済み SurferOnWww 2015年10月18日 3:46 追伸追加
    • 回答としてマーク 星 睦美 2015年10月30日 5:34
    2015年10月18日 3:37
  • 補足します。

    WebClient.DownloadStringメソッド

    このメソッドは、リソースをダウンロードした後、Encodingプロパティに指定されたエンコーディングを使用して、リソースをStringに変換します。

    と説明されています。更にWebClient.Encoding プロパティ

    このプロパティの既定値は、Default によって返されるエンコーディングです。

    と説明されています。ここでEncoding.Defaultは日本語版WindowsであればShift-JISです。しかし実際のコンテンツはUTF-8のようです。

    結局のところ、System.Xmlのバグでもなんでもなく、WebClient.DownloadStringメソッドの使い方誤りです。

    SurferOnWwwさんが書かれているようにXmlDocumentクラスにはダウンロードを行うLoad()メソッドもありますのでこちらを使うべきですが、あえてWebClientクラスを使うのであれば、WebClient.OpenRead()メソッドを用いてStreamを得て、XmlDocument.Load()メソッドにそのStreamを渡すことです。というのもXML仕様にはエンコーディングに関する取り決めもあるため、validなxmlである限り呼び出し側で明示的に指定する必要はありません。


    • 編集済み 佐祐理 2015年10月18日 6:32
    • 回答としてマーク 星 睦美 2015年10月30日 5:34
    2015年10月18日 3:56
  • フォーラム オペレーターの星 睦美です。にっきー さん、投稿ありがとうございます。

    にっきー さんの質問にフォーラムのユーザーからの返信がありますので、確認して返信いただければと思います。
    回答者への良いフィードバックになりますので、参考になった回答には投稿者からの[回答としてマーク] をお願いします。

    ---

    今回は今後の参考になりそうな回答に私のほうで[回答としてマーク] させていただきました。


    フォーラム オペレーター 星 睦美 - MSDN Community Support


    • 編集済み 星 睦美 2015年10月30日 5:37 回答としてマーク
    2015年10月20日 1:43