C#简单的XML读取器跳过了每隔一个元素

3

大家好, 我试图编写一个简单的XML读取器,但发现它无意中跳过了每个XML文件中的其他元素。

我猜我正在告诉它两次移动到下一个元素,但我不确定发生了什么或解决方案是什么。

任何帮助将不胜感激:)

以下是代码示例和XML文件示例:

public LevelLoader(string theLevelFile ,ContentManager theContent)
    {
        XmlTextReader reader = new XmlTextReader(theLevelFile);
        while (reader.Read())
        {               
            if (reader.NodeType == XmlNodeType.Element)
            {
                switch (reader.Name)
                {
                    case "tilerow":
                    {                            
                        currentRow = currentRow + 1;
                        Console.WriteLine("row found");
                        currentCol = 0;
                        break;
                    }

                    case "tilecol":
                    {
                        Console.WriteLine("col found");                                                                                                                         
                        currentTexture = reader.ReadElementContentAsFloat();                          
                        currentCol = currentCol + 1;
                        break;
                    }
                }
            }
        }
    }

示例 XML

<tilerow>
<tilecol>1</tilecol><tilecol>2</tilecol><tilecol>3</tilecol><tilecol>4</tilecol><tilecol>5</tilecol><tilecol>6</tilecol><tilecol>7</tilecol><tilecol>8</tilecol><tilecol>9</tilecol><tilecol>10</tilecol>
</tilerow>

为什么不使用LINQ to XML呢? - Oskar Kjellin
你的样本无法编译。由于存在错误,我们需要看一下代码。 - Les
我的编译通过了,他使用了一些我删除的全局变量。 - Shadow The Spring Wizard
它缺少void,但这不是什么大问题,而且早晨的雾还没有完全消散。 - Les
3个回答

3

Read()方法首先返回Column元素,然后返回Column的“Text”,然后是EndElement。当您使用ReadElementContentAsFloat时,它会读取当前内容,然后将下一个Read()定位到下一个“Text”部分。由于您的循环跳过了Text和EndElement,所以它错过了2, 4, ...

请尝试使用以下方法代替...

case "tilecol": 
{ 
Console.WriteLine("col found");
reader.Read();
float.TryParse(reader.Value, out currentTexture);
currentCol = currentCol + 1;
break;
} 

2

请查看此页面:http://msdn.microsoft.com/en-us/library/ms223980.aspx

简而言之,ReadElementContentAsFloat会将读取器移动到下一个元素,因此它是循环中的“主”reader.Read()。

以下是考虑到这种新行为的新循环:

while (!reader.EOF)
{
    bool needToRead = true;
    if (reader.NodeType == XmlNodeType.Element)
    {
        switch (reader.Name)
        {
            case "tilerow":
                currentRow = currentRow + 1;
                Console.WriteLine("row found");
                currentCol = 0;
                break;

            case "tilecol":
                Console.WriteLine("col found");                                                                                                                         
                currentTexture = reader.ReadElementContentAsFloat();                          
                currentCol = currentCol + 1;
                needToRead = false;
                break;
        }
    }
    if (needToRead)
        reader.Read();
}

0
根据@Shadow Wizard的回答,在可序列化类TileRow中编写自己的ReadXml方法。
public void ReadXml(XmlReader reader)
{
    reader.Read();
    do
    {
        if (!XmlNodeType.Element.Equals(reader.NodeType))
        {
            if (!XmlNodeType.EndElement.Equals(reader.NodeType))
            {
                log.error(reader.NodeType + " is an unknown NodeType for " + this.GetType());
            }
            // return while further reading would move the reader position to another / outer element and will lead to skipped elements in parser
            return;
        }
        switch (reader.Name)
        {
            case "tilecol":
                col = reader.ReadElementContentAsFloat();
                break;

             default:
                log.error(reader.Name + " is not a valid XMLElement for " + this.GetType());
                reader.Read();
                break;
        }
    }
    while (!reader.EOF);
 }

给手册编写者:

public void WriteXml(XmlWriter writer)
{
    writer.WriteElementString("tilecol", col.ToString());
}

所以你可以将TileRow用作XMLElement

[XmlElement]
public TileRow tileRow { get; set; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接