6

Silverlight プロジェクトで XmlReader を使用してファイル リーダーを作成しています。ただし、いくつかのエラー (特に XmlReader.ReadStartElement メソッドの周り) が発生しており、途中で使用方法を誤解していると思われます。

基本的に、私が使用している Xml の形式のサンプルを次に示します。

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<root>
    <EmptyElement />
    <NonEmptyElement Name="NonEmptyElement">
        <SubElement Name="SubElement" />
    </NonEmptyElement>
</root>

そして、これは私がそれを使用しているのと同じ方法で使用されるいくつかのコードのサンプルです:

public void ReadData(XmlReader reader)
{
    // Move to root element
    reader.ReadStartElement("root");

    // Move to the empty element
    reader.ReadStartElement("EmptyElement");

    // Read any children
    while(reader.ReadToNextSibling("SubEmptyElement"))
    {
        // ...
    }

    // Read the end of the empty element
    reader.ReadEndElement();

    // Move to the non empty element
    reader.ReadStartElement("NonEmptyElement");    // NOTE: This is where I get the error.

    // ...
}

したがって、基本的には、各要素とそれに含まれる子を読み取ろうとしているだけです。強調表示されたポイントで発生するエラーは次のとおりです。

エラーの説明

[Xml_InvalidNodeType] 引数: なし、10,8 デバッグ リソース文字列は使用できません。多くの場合、キーと引数は、問題を診断するのに十分な情報を提供します。http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.51204.0&File=System.Xml.dll&Key=Xml_InvalidNodeTypeを参照してください。

エラー スタック トレース

System.Xml.XmlReader.ReadStartElement(文字列名) で ----------------

これに関するアドバイスや指示は大歓迎です。

編集 このリーダーはかなり一般的である必要があるため、Xml には EmptyElement の子である要素が含まれている可能性があると想定できます。そのため、SubEmptyElements の読み取りの試行は有効である必要があります。

4

1 に答える 1

7

<SubElement/>はの兄弟ではない<EmptyElement>ため、<NonEmptyElement>完全にスキップされ、への呼び出しReadEndElement()は終了要素を読み取ります</root>。その後「NonEmptyElement」を読み込もうとすると、要素が残っていないため、XmlExceptionが発生します:{"'None'は無効なXmlNodeTypeです。8行目、1番目の位置。"}

また、<EmptyElement/>空であるため、ReadStartElement( "EmptyElement")を実行すると、要素全体が読み取られ、ReadEndElement()を使用する必要がないことにも注意してください。

また、リーダー設定をIgnoreWhitespaceに構成することをお勧めします(まだ行っていない場合)。これにより、予期しないときに(重要でない)空白テキストノードを読み取ることによって発生する問題を回避できます。

NonEmptyElementの読み取りを上に移動してみてください。

public static void ReadData(XmlReader reader)
{
    reader.ReadStartElement("root");

    reader.ReadStartElement("EmptyElement");

    reader.ReadStartElement("NonEmptyElement");

    while (reader.ReadToNextSibling("SubEmptyElement"))
    {
        // ...
    }

    reader.ReadEndElement(/* NonEmptyElement */);

    reader.ReadEndElement(/* root */);
    // ...
}

<EmptyElement>実際に空であるかどうかに関係なく、で何かをスキップしたい場合は、次を使用しReadToFollowingます。

public static void ReadData(XmlReader reader)
{
    reader.ReadStartElement("root");

    reader.ReadToFollowing("NonEmptyElement");

    Console.WriteLine(reader.GetAttribute("Name"));

    reader.ReadStartElement("NonEmptyElement");

    Console.WriteLine(reader.GetAttribute("Name"));
    while (reader.ReadToNextSibling("SubEmptyElement"))
    {
        // ...
    }

    reader.ReadEndElement(/* NonEmptyElement */);

    reader.ReadEndElement(/* root */);
    // ...
}

更新:これは、より明確なデータモデルを使用したより完全な例です。多分これはあなたが求めているものに近いです。

XMLFile1.xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<root>
  <Person Type="Homeless"/>
  <Person Type="Developer">
    <Home Type="Apartment" />
  </Person>
  <Person Type="Banker">
    <Home Type="Apartment"/>
    <Home Type="Detached"/>
    <Home Type="Mansion">
      <PoolHouse/>
    </Home>
  </Person>
</root>

Program.cs:

using System;
using System.Xml;

namespace ConsoleApplication6
{
    internal class Program
    {
        public static void ReadData(XmlReader reader)
        {
            reader.ReadStartElement("root");

            while (reader.IsStartElement("Person"))
            {
                ReadPerson(reader);
            }

            reader.ReadEndElement( /* root */);
        }

        public static void ReadPerson(XmlReader reader)
        {
            Console.WriteLine(reader.GetAttribute("Type"));
            bool isEmpty = reader.IsEmptyElement;
            reader.ReadStartElement("Person");
            while (reader.IsStartElement("Home"))
            {
                ReadHome(reader);
            }
            if (!isEmpty)
            {
                reader.ReadEndElement( /* Person */);
            }
        }

        public static void ReadHome(XmlReader reader)
        {
            Console.WriteLine("\t" + reader.GetAttribute("Type"));
            bool isEmpty = reader.IsEmptyElement;
            reader.ReadStartElement("Home");

            if (!isEmpty)
            {
                reader.Skip();
                reader.ReadEndElement( /* Home */);
            }
        }

        private static void Main(string[] args)
        {
            var settings = new XmlReaderSettings { IgnoreWhitespace = true };
            using (var xr = XmlReader.Create("XMLFile1.xml", settings))
            {
                ReadData(xr);
            }
            Console.ReadKey();
        }
    }
}
于 2011-02-13T03:52:10.070 に答える