Unityな日々(Unity Geek)

Unityで可視化アプリを開発するための試行錯誤の覚書

XmlDocument()でXMLをパースする その2

XmlDocumentを使ったXMLパース方法の続き。Unity Noobs: XML - Loading data from a xml file.のスクリプトが良い参考になるので、これを解読してみる。

サンプルのXMLは次。

<levels>
  <level>
    <name>Level 1 (xml)</name>
    <tutorial>Try comes close to all four objects. (xml)</tutorial>
    <object name="Cube"> Hi, I'm a cube! (xml) </object>
    <object name="Cylinder"> Hi, I'm a Cylinder! (xml) </object>
    <object name="Capsule"> Hi, I'm a Capsule! (xml) </object>
    <object name="Sphere"> Hi, I'm a Sphere! (xml)</object>
    <finaltext>Very Good! (xml)</finaltext>
  </level>
  <level>
    <name>Level 2 (xml)</name>
    <tutorial>Try comes close to all four objects, again. (xml)</tutorial>
    <object name="Cube"> Hi, I'm a cube in the level 2! (xml)</object>
    <object name="Cylinder"> Hi, I'm a Cylinder in the level 2! (xml)</object>
    <object name="Capsule"> Hi, I'm a Capsule in the level 2! (xml)</object>
    <object name="Sphere"> Hi, I'm a Sphere in the level 2! (xml)</object>
    <finaltext>Congratulations! (xml)</finaltext>
  </level>
</levels>


これに対して次のスクリプトがある。(注:C#で記述されているので、javascript派は読み替えてください。)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
  
  
public class LoadXmlData : MonoBehaviour // the Class
{
 public TextAsset GameAsset;
  
 static string Cube_Character = "";
 static string Cylinder_Character = "";
 static string Capsule_Character = "";
 static string Sphere_Character = "";
  
 List<Dictionary<string,string>> levels = new List<Dictionary<string,string>>();
 Dictionary<string,string> obj;
  
 void Start()
 { //Timeline of the Level creator
  GetLevel();
 }
  
 public void GetLevel()
 {
  XmlDocument xmlDoc = new XmlDocument(); // xmlDoc is the new xml document.
  xmlDoc.LoadXml(GameAsset.text); // load the file.
  XmlNodeList levelsList = xmlDoc.GetElementsByTagName("level"); // array of the level nodes.
  
  foreach (XmlNode levelInfo in levelsList)
  {
   XmlNodeList levelcontent = levelInfo.ChildNodes;
   obj = new Dictionary<string,string>(); // Create a object(Dictionary) to colect the both nodes inside the level node and then put into levels[] array.
    
   foreach (XmlNode levelsItens in levelcontent) // levels itens nodes.
   {
    if(levelsItens.Name == "name")
    {
     obj.Add("name",levelsItens.InnerText); // put this in the dictionary.
    }
    
    if(levelsItens.Name == "tutorial")
    {
     obj.Add("tutorial",levelsItens.InnerText); // put this in the dictionary.
    }
    
    if(levelsItens.Name == "object")
    {
     switch(levelsItens.Attributes["name"].Value)
     {
      case "Cube": obj.Add("Cube",levelsItens.InnerText);break; // put this in the dictionary.
      case "Cylinder":obj.Add("Cylinder",levelsItens.InnerText); break; // put this in the dictionary.
      case "Capsule":obj.Add("Capsule",levelsItens.InnerText); break; // put this in the dictionary.
      case "Sphere": obj.Add("Sphere",levelsItens.InnerText);break; // put this in the dictionary.
     }
    }
    
    if(levelsItens.Name == "finaltext")
    {
     obj.Add("finaltext",levelsItens.InnerText); // put this in the dictionary.
    }
   }
   levels.Add(obj); // add whole obj dictionary in the levels[].
  }
 }
}

XmlDocumentファミリーを使う際の肝は次の通り。(注:僕はjavascript派なので、javascriptに書き換えている)

1)XMLを読み込む

xmlDoc:XmlDocument  = new XmlDocument(); 
xmlDoc.LoadXml(GameAsset.text); 

2)"lavel"と言う名前のタグのみ抜き出したXmlList(Array)を作る。

levelsList: XmlNodeList = xmlDoc.GetElementsByTagName("level"); 

ちなみにタグ名ではなく、num番目(0,1,2,...)の要素を取り出すには、

levelsList: XmlNodeList = xmlDoc.GetElementsById(num); 

とする。

3)XmlList("levelList")から、要素であるXmlNodeをひとつずつ取り出す。
 (注:javascriptでは’foreach'は使えないので'for'で代用。'var'が必要なことも注意)

for (var levelInfo:XmlNode  in levelsList){

4)XmlNodeから子ノードのXmlListを作る。

levelcontent:XmlNodeList = levelInfo.ChildNodes;

5)XmlNodeのタグ名は、'XmlNode名.Name'で取得。

if(levelsItens.Name == "name")

6)XmlNodeのテキストは、'XmlNode名.InnerText'で取得。

obj.Add("name",levelsItens.InnerText);

7)XmlNodeのアトリビュートは、'XmlNode名.Attributes["アトリビュート名"].Value'で取得。

switch(levelsItens.Attributes["name"].Value)