需要帮助将XML数据加载到XNA 4.0项目中

时间:2010-06-30 15:16:35

标签: xml-serialization xna xna-4.0

如果可能的话,我想以正确的方式做到这一点。我有如下XML数据:

<?xml version="1.0" encoding="utf-8"?>
    <XnaContent>
        <Asset Type="PG2.Dictionary">
            <Letters TotalInstances="460100">
                <Letter Count="34481">&#97;</Letter>
                ...
                <Letter Count="1361">&#122;</Letter>
            </Letters>
            <Words Count="60516">
                <Word>aardvark</Word>
                ...
                <Word>zebra</Word>
            </Words>
        </Asset>
    </XnaContent>

我想将其加载(使用Content.Load&lt; Dictionary&gt;)到其中一个

namespace PG2
{
    public class Dictionary
    {
        public class Letters
        {
            public int totalInstances;

            public List<Character> characters;

            public class Character
            {
                public int count;
                public char character;
            }
        }

        public class Words
        {
            public int count;
            public HashSet<string> words;
        }

        Letters letters;
        Words words;
    }
}

任何人都可以帮助指导或指导教程吗?我发现了一些接近但事情似乎在3.1和4.0之间略有变化的方式,我不明白,很多文档假定我没有的知识。到目前为止,我的理解是我需要使Dictionary类Serializable,但我似乎无法实现这一点。我已将XML文件添加到内容项目中,但如何让它创建正确的XNB文件?

谢谢! 查理。

2 个答案:

答案 0 :(得分:1)

这可能有助http://blogs.msdn.com/b/shawnhar/archive/2009/03/25/automatic-xnb-serialization-in-xna-game-studio-3-1.aspx。我发现反过来检查我的xml数据是否正确定义是有用的。立即将字典类设置为所有字段,然后使用XmlSerializer将其序列化为xml以检查输出。

答案 1 :(得分:0)

您需要为Dictionary类实现ContentTypeSerializer。将其放在内容扩展库中,并将内容扩展库的引用添加到内容项目中。将您的Dictionary类放入游戏库,该游戏库将由您的游戏和内容扩展项目引用。

请参阅: http://blogs.msdn.com/b/shawnhar/archive/2008/08/26/customizing-intermediateserializer-part-2.aspx

这是我编写的一个快速的ContentTypeSerializer,它将反序列化您的Dictionary类。它可以使用更好的错误处理。

using System;
using System.Collections.Generic;
using System.Xml;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;

namespace PG2
{
    [ContentTypeSerializer]
    class DictionaryXmlSerializer : ContentTypeSerializer<Dictionary>
    {
        private void ReadToNextElement(XmlReader reader)
        {
            reader.Read();

            while (reader.NodeType != System.Xml.XmlNodeType.Element)
            {
                if (!reader.Read())
                {
                    return;
                }
            }
        }

        private void ReadToEndElement(XmlReader reader)
        {
            reader.Read();

            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                reader.Read();
            }
        }

        private int ReadAttributeInt(XmlReader reader, string attributeName)
        {
            reader.MoveToAttribute(attributeName);
            return int.Parse(reader.Value);
        }

        protected override Dictionary Deserialize(IntermediateReader input, Microsoft.Xna.Framework.Content.ContentSerializerAttribute format, Dictionary existingInstance)
        {
            Dictionary dictionary = new Dictionary();
            dictionary.letters = new Dictionary.Letters();
            dictionary.letters.characters = new List<Dictionary.Letters.Character>();
            dictionary.words = new Dictionary.Words();
            dictionary.words.words = new HashSet<string>();

            ReadToNextElement(input.Xml);
            dictionary.letters.totalInstances = ReadAttributeInt(input.Xml, "TotalInstances");

            ReadToNextElement(input.Xml);

            while (input.Xml.Name == "Letter")
            {
                Dictionary.Letters.Character character = new Dictionary.Letters.Character();

                character.count = ReadAttributeInt(input.Xml, "Count");

                input.Xml.Read();
                character.character = input.Xml.Value[0];

                dictionary.letters.characters.Add(character);
                ReadToNextElement(input.Xml);
            }

            dictionary.words.count = ReadAttributeInt(input.Xml, "Count");

            for (int i = 0; i < dictionary.words.count; i++)
            {
                ReadToNextElement(input.Xml);
                input.Xml.Read();
                dictionary.words.words.Add(input.Xml.Value);
                ReadToEndElement(input.Xml);
            }

            ReadToEndElement(input.Xml);    // read to the end of words
            ReadToEndElement(input.Xml);    // read to the end of asset

            return dictionary;
        }

        protected override void Serialize(IntermediateWriter output, Dictionary value, Microsoft.Xna.Framework.Content.ContentSerializerAttribute format)
        {
            throw new NotImplementedException();
        }
    }
}