1

XMLの書き込みと読み取りに問題があります。手書きのXMLは正常に読み取られますが、XMLを書き込んだ後はおかしな動作をします。

WriteXMLの出力:http ://www.craigmouser.com/random/test.xml

(スペシャル)タグの後にEnterキーを押すと機能します。IE make(specials)(special)like

(スペシャル)
(スペシャル)

ステップスルーすると、それを読み取るときに、スペシャルの開始ノードに移動し、次の反復で、Shotsという名前のEndElementとして読み取られます。ここからどこへ行けばいいのかわからない。前もって感謝します。

コード:書く

        public void SaveXMLFile(string filename, Bar b, Boolean saveOldData)
    {
        XmlWriter xml;
        if(filename.Contains(".xml"))
        {
            xml = XmlWriter.Create(filename);
        }
        else 
        {
            xml = XmlWriter.Create(filename + ".xml");
        }
        xml.WriteStartElement("AggievilleBar");
        xml.WriteElementString("name", b.Name);
        xml.WriteStartElement("picture");
        xml.WriteAttributeString("version", b.PictureVersion.ToString());
        xml.WriteEndElement();
        xml.WriteElementString("location", b.Location.Replace(Environment.NewLine, "\n"));
        xml.WriteElementString("news", b.News.Replace(Environment.NewLine, "\n"));
        xml.WriteElementString("description", b.Description.Replace(Environment.NewLine, "\n"));
        xml.WriteStartElement("specials");
        xml.WriteString("\n"); //This line fixes the problem... ?!?!
        foreach (Special s in b.Specials)
        {
            if (s.DayOfWeek > 0 || (s.DayOfWeek == -1 
                && ((s.Date.CompareTo(DateTime.Today) < 0 && saveOldData )
                || s.Date.CompareTo(DateTime.Today) >= 0)))
            {
                    xml.WriteStartElement("special");
                    xml.WriteAttributeString("dayofweek", s.DayOfWeek.ToString());
                    if (s.DayOfWeek == -1)
                        xml.WriteAttributeString("date", s.Date.ToString("yyyy-MM-dd"));
                    xml.WriteAttributeString("price", s.Price.ToString());
                    xml.WriteString(s.Name);
                    xml.WriteEndElement();
            }
        }
        xml.WriteEndElement();
        xml.WriteEndElement();
        xml.Close();
    }

コード:読書

        public Bar LoadXMLFile(string filename)
    {
        List<Special> specials = new List<Special>();
        XmlReader xml;
        try
        {
            xml = XmlReader.Create(filename);
        }
        catch (Exception)
        {

            MessageBox.Show("Unable to open file. If you get this error upon opening the program, we failed to pull down your current data. You will most likely be unable to save, but you are free to try. If this problem persists please contact us at pulsarproductionssupport@gmail.com",
                "Error Opening File", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return null;
        }

        Bar current = new Bar();
        Special s = new Special();
        while (xml.Read())
        {
            if (xml.IsStartElement())
            {
                switch (xml.Name)
                {
                    case "AggievilleBar":
                        current = new Bar();
                        break;
                    case "name":
                        if (xml.Read())
                            current.Name = xml.Value.Trim();
                        break;
                    case "picture":
                        if (xml.HasAttributes)
                        {
                            try
                            {
                                current.PictureVersion = Int32.Parse(xml.GetAttribute("version"));
                            }
                            catch (Exception)
                            {

                                MessageBox.Show("Error reading in the Picture Version Number.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
                            }
                        } 
                        break;
                    case "location":
                        if (xml.Read())
                            current.Location = xml.Value.Trim();
                        break;
                    case "news":
                        if (xml.Read())
                            current.News = xml.Value.Trim();
                        break;
                    case "description":
                        if (xml.Read())
                            current.Description = xml.Value.Trim();
                        break;
                    case "specials":
                        if (xml.Read())
                            specials = new List<Special>();
                        break;
                    case "special":
                        s = new Special();
                        if (xml.HasAttributes)
                        {
                            try
                            {
                                s.DayOfWeek = Int32.Parse(xml.GetAttribute(0));
                                if (s.DayOfWeek == -1)
                                {
                                    s.Date = DateTime.Parse(xml.GetAttribute(1));
                                    s.Price = Int32.Parse(xml.GetAttribute(2));
                                }
                                else
                                    s.Price = Int32.Parse(xml.GetAttribute(1));
                            }
                            catch (Exception)
                            {

                                MessageBox.Show("Error reading in a special.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }
                        if (xml.Read())
                            s.Name = xml.Value.Trim();
                        break;
                }
            }
            else
            {
                switch (xml.Name)
                {
                    case "AggievilleBar":
                        xml.Close();
                        break;
                    case "special":
                        specials.Add(s);
                        break;
                    case "specials":
                        current.Specials = specials;
                        break;
                }
            }
        }

        return current;
    }
4

2 に答える 2

1

あなたのコードを見ずに、その質問に正直に答えることは難しいです。ただし、XMLReader / XMLWriterの代わりにLinq-to-XMLを使用することをお勧めします。各ノードを一度に1つずつ読み取り、操作しているノードを判別する必要がない場合は、操作が非常に簡単です。あなたが抱えている問題のように聞こえます。

たとえば、次のようなコードを使用します。

using (var reader = new XmlReader(...))
{
    while reader.Read()
    {
        if (reader.Name = "book" && reader.IsStartElement)
        {
            // endless, confusing nesting!!!
        }
    }
}

になる:

var elem = doc.Descendants("book").Descendants("title")
           .Where(c => c.Attribute("name").Value == "C# Basics")
           .FirstOrDefault();

LINQ-to-XMLの概要については、http: //www.c-sharpcorner.com/UploadFile/shakthee/2868/を確認するか、「Linq-to-XML」を検索してください。そこにたくさんの例。

編集:私はあなたのコードを試しました、そして私はあなたの問題を再現することができました。specialタグの前に改行がない場合、最初のspecial要素はとして読み込まれるようIsStartElement() == falseです。これがなぜなのかわかりませんでした。XML仕様をざっと見ても、要素の前に改行に関する要件はありませんでした。

私はあなたのコードをLinq-to-XMLで書き直しました、そしてそれは改行なしでうまく働きました:

var xdoc = XDocument.Load(filename);
var barElement = xdoc.Element("AggievilleBar");
var specialElements = barElement.Descendants("special").ToList();
var specials = new List<Special>();
specialElements.ForEach(s =>
    {
        var dayOfWeek = Convert.ToInt32(s.Attribute("dayofweek").Value);
        var price = Convert.ToInt32(s.Attribute("price").Value);
        var date = s.Attribute("date");
        specials.Add(new Special
        {
            Name = s.Value,
            DayOfWeek = dayOfWeek,
            Price = price,
            Date = date != null ? DateTime.Parse(date.Value) : DateTime.MinValue
        });
    });
var bar = new Bar() {
    Name = barElement.Element("name").Value,
    PictureVersion = Convert.ToInt32(barElement.Elements("picture").Single()
        .Attribute("version").Value),
    Location = barElement.Element("location").Value,
    Description = barElement.Element("description").Value,
    News = barElement.Element("news").Value,
    Specials = specials
};
return bar;

XMLReaderの代わりにLinq-to-XMLを使用することを検討しますか?私は過去にXMLReaderで問題を抱えていましたが、Linq-to-XMLに切り替えた後は振り返りませんでした。

編集:私はこの質問がかなり古いことを知っていますが、私はこの質問を思い出させ、なぜこれが起こっているのかを説明するかもしれない記事に出くわしました:-> http://www.codeproject.com/KB/dotnet/pitfalls_xml_4_0 .aspx

著者は次のように述べています。

この観点から、XmlReaders / WritersとXDocumentの厄介な違いは、空白の処理方法です。(http://msdn.microsoft.com/en-us/library/bb387014.aspxを参照してください。)

msdnから:

ほとんどの場合、メソッドがLoadOptionsを引数として取る場合、オプションで、重要でない空白をXMLツリーのテキストノードとして保持できます。ただし、メソッドがXmlReaderからXMLをロードしている場合、XmlReaderは空白を保持するかどうかを決定します。PreserveWhitespaceを設定しても効果はありません。

したがって、おそらく、XmlReaderを使用してロードしているため、XmlReaderは、空白を保持する必要があるかどうかを判断しています。ほとんどの場合、空白を保持しているため、改行(または改行の欠如)が違いを生みます。そして、XmlReaderを使用している限り、それを変更するために何もできないようです。非常に独特です。

于 2010-12-12T07:10:27.203 に答える
1

XmlDocumentクラスとそのLoadandメソッドを使用してから、 andSaveをいじる代わりにXMLツリーを操作することをお勧めします。私の経験では、使用すると奇妙なフォーマットの問題が少なくなります。XmlReaderXmlWriterXmlDocument

于 2010-12-13T01:41:26.560 に答える