블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2731)
Unity3D (814)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (57)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (51)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
03-29 07:22

TinyXmlReader

Unity3D/Xml / 2012. 12. 9. 20:29

TinyXmlReader

You can use Mono's System.Xml for handling XML files but this requires including the System.Xml dll into your Unity program which increases its file size by about 1 MB. Not to mention the lack of documentation for using System.Xml on UnityScript.

I found rolling my own XML parser was easier. Note however that this is a really simple XML parser, it doesn't recognize attributes (I did not implement it simply because I don't use XML attributes).

TinyXmlReader.cs

using UnityEngine;
using System.Collections;
 
public class TinyXmlReader
{
    private string xmlString = "";
    private int idx = 0;
 
    public TinyXmlReader(string newXmlString)
    {
        xmlString = newXmlString;
    }
 
    public string tagName = "";
    public bool isOpeningTag = false;
    public string content = "";
 
 
	// properly looks for the next index of _c, without stopping at line endings, allowing tags to be break lines	
	int IndexOf(char _c, int _i)
	{
		int i = _i;
		while (i < xmlString.Length)
		{
			if (xmlString[i] == _c)
				return i;
 
			++i;
		}
 
		return -1;
	}
 
    public bool Read()
    {
		if (idx > -1)
        	idx = xmlString.IndexOf("<", idx);
 
        if (idx == -1)
        {
            return false;
        }
        ++idx;
 
		// skip attributes, don't include them in the name!
		int endOfTag = IndexOf('>', idx);
		int endOfName = IndexOf(' ', idx);
        if ((endOfName == -1) || (endOfTag < endOfName))
	    {
			endOfName = endOfTag;
		}
 
		if (endOfTag == -1)
        {
            return false;
        }
 
        tagName = xmlString.Substring(idx, endOfName - idx);
 
        idx = endOfTag;
 
        // check if a closing tag
        if (tagName.StartsWith("/"))
        {
            isOpeningTag = false;
            tagName = tagName.Remove(0, 1); // remove the slash
        }
        else
        {
            isOpeningTag = true;
        }
 
        // if an opening tag, get the content
        if (isOpeningTag)
        {
            int startOfCloseTag = xmlString.IndexOf("<", idx);
            if (startOfCloseTag == -1)
            {
                return false;
            }
 
            content = xmlString.Substring(idx+1, startOfCloseTag-idx-1);
            content = content.Trim();
        }
 
        return true;
    }
 
    // returns false when the endingTag is encountered
    public bool Read(string endingTag)
    {
        bool retVal = Read();
        if (tagName == endingTag && !isOpeningTag)
        {
            retVal = false;
        }
        return retVal;
    }
}

TinyXmlReader.js

class TinyXmlReader
{
 
private var xmlString = "";
private var idx = 0;
 
function TinyXmlReader(aXmlString : String)
{
	xmlString = aXmlString;
}
 
var tagName = "";
var isOpeningTag = false;
var content = "";
 
function Read() : boolean
{
	idx = xmlString.IndexOf("<", idx);
	if (idx == -1)
	{
		return false;
	}
	++idx;
 
	var endOfTag = xmlString.IndexOf(">", idx);
	if (endOfTag == -1)
	{
		return false;
	}
 
	tagName = xmlString.Substring(idx, endOfTag-idx);
 
	idx = endOfTag;
 
	// check if a closing tag
	if (tagName.StartsWith("/"))
	{
		isOpeningTag = false;
		tagName = tagName.Remove(0, 1); // remove the slash
	}
	else
	{
		isOpeningTag = true;
	}
 
	// if an opening tag, get the content
	if (isOpeningTag)
	{
		var startOfCloseTag = xmlString.IndexOf("<", idx);
		content = xmlString.Substring(idx+1, startOfCloseTag-idx-1);
		content = content.Trim();
	}
 
	return true;
}
 
// returns false when the endingTag is encountered
function Read(endingTag : String) : boolean
{
	var retVal = Read();
	if (tagName == endingTag && !isOpeningTag)
	{
		retVal = false;
	}
	return retVal;
}
 
}

Usage

Here I provide example code on how to use the TinyXmlReader.

private var text : String;
var skin : GUISkin;
 
function OnGUI()
{
	GUILayout.Label(text, skin.label);
}
 
function Start()
{
	var xmlText = System.IO.File.ReadAllText(Application.dataPath + "/Rifleman.xml");
	var reader = TinyXmlReader(xmlText);
	while (reader.Read())
	{
		if (reader.isOpeningTag)
		{
			text += (reader.tagName + " \"" + reader.content + "\"\n");
		}
		if (reader.tagName == "Skills" && reader.isOpeningTag)
		{
			while(reader.Read("Skills")) // read as long as not encountering the closing tag for Skills
			{
 
				if (reader.isOpeningTag)
				{
					text += ("Skill: " + reader.tagName + " \"" + reader.content + "\"\n");
				}
			}
		}
	}
}

Plus, here's the XML file used for the example code: <xml> <?xml version="1.0" encoding="UTF-8"?> <Unit> <Type>Rifleman</Type> <Label>ライフル銃兵 é (для Windows тоже!)</Label> <MaxHP>100</MaxHP> <SightRange>10</SightRange> <Skills> <UnitMovement> <Label>Move</Label> <Animation>move</Animation> <Range>10</Range> <Speed>6</Speed> </UnitMovement> <SimpleAttack> <Label>Attack</Label> <Animation>shoot</Animation> <Range>10</Range> <Damage>20</Damage> <AttackTime>0.348</AttackTime> <AttackType>Ranged</AttackType> </SimpleAttack> <Grenade> <Label>Throw Grenade</Label> <Animation>shoot</Animation> <Range>10</Range> <Damage>20</Damage> <AttackTime>0.348</AttackTime> <ExplosionRadius>5</ExplosionRadius> <NoOfUses>3</NoOfUses> </Grenade> </Skills> <Pahabol>oompa loompa doompity doo, we wouldn't hit that and neither should you</Pahabol> </Unit> </xml>

It produces this output:

TinyXmlReader Sample Output


출처 : http://wiki.unity3d.com/index.php/TinyXmlReader

반응형
Posted by blueasa
, |