2014-01-21 2 views
0

다중 레벨의 XML 파일을 읽고 객체 목록에 저장하고 싶습니다. XML 파일은 gender를 가지고 있으며, gender는 attributemodifier와 0-n 스킬 수정자를 0에서 n까지 보유합니다. attributemodifiers resp를 가정 할 수 있습니다. skillmodifiers 태그는 항상 존재합니다. 자식 노드 "attributemodifiers"와 "skillmodifiers"를로드 할 때 실패합니다. 내 질문은 그 이유입니다.C에서 다중 레벨 XML 파일 읽기

<?xml version="1.0" encoding="UTF-8"?> 
<genders> 
    <gender> 
     <name>Female</name> 
     <attributemodifiers> 
      <attributemodifier> 
       <attribute>Agility</attribute> 
       <value>1</value> 
      </attributemodifier> 
     </attributemodifiers>  
     <skillmodifiers> 
      <skillmodifier> 
       <attribute>Charm</attribute> 
       <value>1</value> 
      </skillmodifier> 
     </skillmodifiers> 
    </gender> 
    <gender> 
     <name>Male</name> 
     <attributemodifiers> 
      <attributemodifier> 
       <attribute>Strength</attribute> 
       <value>1</value> 
      </attributemodifier> 
      <attributemodifier> 
       <attribute>Focus</attribute> 
       <value>-1</value> 
      </attributemodifier> 
     </attributemodifiers>  
     <skillmodifiers> 
      <skillmodifier> 
       <attribute>Intimidation</attribute> 
       <value>1</value> 
       <attribute>Coercion</attribute> 
       <value>1</value> 
      </skillmodifier> 
     </skillmodifiers> 
    </gender> 
</genders> 

현재 코드는 내가 가진 :

XmlDocument doc = new XmlDocument(); 
doc.Load (@"genders.xml"); 

XmlNodeList gs = doc.SelectNodes ("genders/gender"); 

foreach (XmlNode g in gs) { 

    Gender tg = new Gender(); 
    tg.Name = g.SelectSingleNode("name").InnerText; 
    tg.Desc = g.SelectSingleNode("desc").InnerText; 

    XmlNodeList ams = doc.ChildNodes; 

    foreach (XmlNode am in ams) { 
     int ta = (int)System.Enum.Parse(typeof(AttributeName), am.SelectSingleNode ("attribute").InnerText); 
     int tv = System.Convert.ToInt32(am.SelectSingleNode ("value").InnerText); 
     tg.AddAttributeModifier (ta, tv); 
    } 

    XmlNodeList sms = doc.ChildNodes; 

    foreach (XmlNode sm in sms) { 
     int ts = (int)System.Enum.Parse(typeof(SkillName), sm.SelectSingleNode ("skill").InnerText); 
     int tv = System.Convert.ToInt32(sm.SelectSingleNode ("value").InnerText); 
     tg.AddSkillModifier (ts, tv); 
    } 

    genders.Add (tg); 
    length++; 

    Debug.Log ("Increased length by 1, length is now " + length); 
} 

나에게 코드가 자식 노드 인에 실패 3 그래서 부분의 길이를 줄 것이다 루프 내 내부 주석 달기.

int ta = (int)System.Enum.Parse(typeof(AttributeName), am.SelectSingleNode ("attribute").InnerText); 

내가 childNodes에 내가이 일을 예상대로 작동하지 않는 것으로 가정하기 위하여려고하고있다

그 라인

NullReferenceException: Object reference not set to an instance of an object 
GenderManager.Awake() (at Assets/Scripts/Managers/GenderManager.cs:36) 

.

성별 클래스 (gender.cs)

using System.Collections.Generic; 

public class Gender { 

    private string _name; 
    private string _desc; 
    private List<GenderBonusAttribute> _attributeMods; 
    private List<GenderBonusSkill> _skillMods; 

    public Gender() { 
     _name = string.Empty; 
     _attributeMods = new List<GenderBonusAttribute>(); 
     _skillMods = new List<GenderBonusSkill>(); 
    } 

    public string Name { 
     get {return _name;} 
     set {_name = value;} 
    } 

    public string Desc { 
     get {return _desc;} 
     set {_desc = value;} 
    } 

    public void AddAttributeModifier (int a, int v) { 
     _attributeMods.Add (new GenderBonusAttribute (a, v)); 
    } 

    public void AddSkillModifier (int s, int v) { 
     _skillMods.Add (new GenderBonusSkill (s, v)); 
    } 

    public List<GenderBonusAttribute> AttributeMods { 
     get {return _attributeMods;} 
    } 

    public List<GenderBonusSkill> SkillMods { 
     get {return _skillMods;} 
    } 
} 

public class GenderBonusAttribute { 
    public int attribute; 
    public int value; 

    public GenderBonusAttribute (int a, int v) { 
     attribute = a; 
     value = v; 
    } 
} 

public class GenderBonusSkill { 
    public int skill; 
    public int value; 

    public GenderBonusSkill (int s, int v) { 
     skill = s; 
     value = v; 
    } 
} 

편집 : 추가 AttributeName에와 SkillName는

public enum AttributeName { 
    Strength, 
    Agility, 
    Quickness, 
    Endurance, 
    Attunement, 
    Focus 
}; 

public enum SkillName { 
    Weight_Capacity, 
    Attack_Power, 
    Intimidation, 
    Coercion, 
    Charm 
} 

편집 # 2 : 나는 수동으로 값으로 성별을 추가 할 경우 작동, 그래서 99.8 %는 foreach 루프가 작동하지 않는다는 것을 확신합니다. 이것은 의사에게 꽤 확신을줍니다. 자식 노드가 작동하지 않을 것이라고 생각합니다.

+0

'SkillName'과'AttributeName'은 어떻게 생겼습니까? – MarcinJuraszek

답변

1

왜 루프 내에 doc.ChildNodes을 사용하고 현재 gender 요소를 사용하지 않습니까?

XmlNodeList ams = g.SelectNodes("attributemodifiers/attributemodifier"); 
XmlNodeList sms = g.SelectNodes("skillmodifiers/skillmodifier"); 

PS :에

변경에게 모두 amssms 선언. LINQ to XML을 사용하지 않는 이유는 무엇입니까? LINQ를 사용하면 훨씬 쉬울 것입니다.

+0

나는 그 (것)들을 첫째로 시도했다. Wierd, 나는 그들을 잘못 사용했거나 철자가 틀린 것 같아요. 고맙습니다, 지금은 작동합니다 (제 XML 파일에 약간의 형편없는 오류가 있다는 것을 제외하고, 고맙게도 디버그가 나를 처리했습니다). 사용하지 않는 특별한 이유가 없습니다. 그것은 권위가 있습니까? – Emz

+0

. NET에서 XML을 다루는보다 새롭고 개발 친화적 인 방법입니다. 나는 지금 XmlDocument를 사용하는 해결책을 가지고있을 때 전환 할 것을 조언하지 않지만, 새로운 코드를 위해서 LINQ to XML을 시도하는 것을 고려해야한다. – MarcinJuraszek

+0

더 빠르고 안전합니까? 더 나은 예외 처리가 있습니까? – Emz