Job’s Done
Here we go. I’ll probably work out little tags to add (Champion, WarMachine, MagicItem, etc) later, but this is a working backbone. I don’t like the text replace messiness in the middle of my code, but I’m too lazy to write a crummy little Boolean method to look at the string and replace what I don’t want. Mebbe this can be done with Regex too? Probably. I don’t know enough about it.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml.XPath;
namespace RosterParserTest
{
class XmlParser
{
static XmlDocument Roster = new XmlDocument();
static XmlElement rootElement = Roster.CreateElement("", "Army", "");
public static string RemoveWhitespace(string str)
{
try
{
//Ryan's Regex
return new Regex(@"(\s+|\{.*?\}|\(.*?\)|\/+|\.+)").Replace(str, String.Empty);
}
catch (Exception)
{
return str;
}
}
public void ParseNestedXML(XmlElement thisElement, XmlElement rosterElement)
{
bool linkUnitStatsDone = false; //This is a dirty hack.
string replaceMe = thisElement.GetAttribute("name").ToString();
replaceMe = RemoveWhitespace(replaceMe);
XmlElement baseElement;
XmlNodeList linkUnitStatNodeList = thisElement.SelectNodes("./link | ./unitstat");
if (rosterElement.Name.ToString() == replaceMe) //So that I don't get duplicate empty nodes.
{
baseElement = rosterElement; //Adding to the previous node in the tree.
foreach (XmlElement parseElement in thisElement)
{
if (parseElement.HasChildNodes && parseElement.InnerXml.Contains("entity"))
{
ParseNestedXML(parseElement, baseElement); //Parsing out nested.
} //if (parseElement.HasChildNodes && parseElement.InnerXml.Contains("entity"))
else if (!linkUnitStatsDone)
{
ParseLinkUnitStats(linkUnitStatNodeList, baseElement);
linkUnitStatsDone = true; //Hack implemented.
} //else if (!linkUnitStatsDone)
} //foreach (XmlElement parseElement in thisElement)
}
else
{
baseElement = Roster.CreateElement(replaceMe);
foreach (XmlElement parseElement in thisElement)
{
if (parseElement.HasChildNodes && parseElement.InnerXml.Contains("entity"))
{
ParseNestedXML(parseElement, baseElement); //Whee recursion.
} //if (parseElement.HasChildNodes && parseElement.InnerXml.Contains("entity"))
else
{
ParseLinkUnitStats(parseElement, baseElement); //This has always worked.
} //else
rosterElement.AppendChild(baseElement); //Add to the local node.
rootElement.AppendChild(rosterElement); //Add to the Army node.
} //foreach (XmlElement parseElement in thisElement)
} //else
} //public void ParseNestedXML(XmlElement thisElement, XmlElement rosterElement)
public void ParseRoster(string path, string output)
{
XmlDocument parsingRoster = new XmlDocument();
parsingRoster.Load(path);
XmlNodeList parsingElements = parsingRoster.SelectNodes("/document/squad");
foreach (XmlElement thisElement in parsingElements)
{
XmlElement rosterElement = Roster.CreateElement("Unit");
ParseNestedXML(thisElement, rosterElement);
} //foreach (XmlElement thisElement in parsingElements)
Roster.AppendChild(rootElement);
Roster.Save(output);
} //public void ParseRoster(string path, string output)
public void ParseLinkUnitStats(XmlElement parseElement, XmlElement baseElement)
{
foreach (XmlElement correctElement in parseElement)
{
if (correctElement.HasAttribute("name"))
{
string subReplaceMe = correctElement.GetAttribute("name").ToString();
subReplaceMe = RemoveWhitespace(subReplaceMe);
XmlElement addElement = Roster.CreateElement(subReplaceMe);
if (subReplaceMe == "BigUnsCoun" || subReplaceMe == "NetCount" || subReplaceMe == "ItemPts"
|| subReplaceMe == "EffCount" || subReplaceMe == "Group" || subReplaceMe == "ItemTagsHelper"
|| subReplaceMe == "ItemCostWorker" || subReplaceMe == "BannerCostWorker")
{
//Remove tags I don't want.
} //if LotsOfCrap
else
{
if (correctElement.HasAttribute("description"))
{
addElement.InnerText = correctElement.GetAttribute("description").ToString();
} //if correctElement.HasAttribute("description"))
else if (correctElement.HasAttribute("value") && (Regex.Match(correctElement.GetAttribute("value").ToString(), @"[^0|-]").Success))
{
addElement.InnerText = correctElement.GetAttribute("value").ToString();
} //else if (correctElement.HasAttribute("value"))
baseElement.AppendChild(addElement);
} //else
} //if (correctElement.HasAttribute("name")
} //foreach (XmlElement correctElement in parseElement)
} //public void ParseLinkUnitStats(XmlElement parseElement, XmlElement baseElement)
public void ParseLinkUnitStats(XmlNodeList parseNodeList, XmlElement baseElement)
{
foreach (XmlElement correctElement in parseNodeList)
{
if (correctElement.HasAttribute("name"))
{
string subReplaceMe = correctElement.GetAttribute("name").ToString();
subReplaceMe = RemoveWhitespace(subReplaceMe);
if (subReplaceMe == "BigUnsCoun" || subReplaceMe == "NetCount" || subReplaceMe == "ItemPts"
|| subReplaceMe == "EffCount" || subReplaceMe == "Group" || subReplaceMe == "ItemTagsHelper"
|| subReplaceMe == "ItemCostWorker" || subReplaceMe == "BannerCostWorker")
{
//Remove tags I don't want.
} //if LotsOfCrap
else
{
XmlElement addElement = Roster.CreateElement(subReplaceMe);
if (correctElement.HasAttribute("description"))
{
addElement.InnerText = correctElement.GetAttribute("description").ToString();
baseElement.AppendChild(addElement);
} //if (correctElement.HasAttribute("description"))
else if (correctElement.HasAttribute("value") && (Regex.Match(correctElement.GetAttribute("value").ToString(), @"[^0|-]").Success))
{
addElement.InnerText = correctElement.GetAttribute("value").ToString();
baseElement.AppendChild(addElement);
} //else if (correctElement.HasAttribute("value"))
} //else
} //if (correctElement.HasAttribute("name"))
} //foreach (XmlElement correctElement in parseNodeList)
} //public void ParseLinkUnitStats(XmlNodeList parseNodeList, XmlElement baseElement)
} //class XmlParser
} //namespace RosterParserTest
And the XML…
+1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 4+ Armor Save 3 9 3 4+ 4 5 6 4+* 3 2 4 2 +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 4+ Armor Save +1 Armour save bonus. 2 9 3 3+/2+ 4 4 5 4+* 1 1 3 1 0+ 5 During opponents magic phase, steal 1 power die to use as a dispel die +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 4+ Armor Save 3 9 3 4+ 4 5 1 6 2 3 4 The unit causes Fear. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. +2 Strength when on foot; +1 Strength if mounted. Always strikes last unless charging. Two-handed. 4+ Armor Save 3 9 3 1+ 4/6 5 1 6 2 3 4 1+ Armor Save, cannot be improved. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 30" Range, Strength 4, Move or Fire. 6+ Armour save. 2 9 3 6+ 3 4 1 4 1 1 3 +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 30" Range, Strength 4, Move or Fire. 6+ Armour save. 2 9 3 6+ 3 4 1 4 1 1 3 +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 5+ Armour save. +1 Armour save bonus. 2 9 3 4+/3+ 3 4 1 4 1 2 3 +1 to combat resolution in a tie. +1 Leadership when attempting to Rally (may not exceed 10). +1 to Combat Resolution; Standard can be captured if unit Flees. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 5+ Armour save. +1 Armour save bonus. 2 9 3 4+/3+ 3 4 1 4 1 1 3 +1 WS, +1 Strength. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. +2 Strength when on foot; +1 Strength if mounted. Always strikes last unless charging. Two-handed. 5+ Armour save. 2 9 3 5+ 4/6 4 1 5 1 2 3 +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. +2 Strength when on foot; +1 Strength if mounted. Always strikes last unless charging. Two-handed. 5+ Armour save. 2 9 3 5+ 4/6 4 1 5 1 2 3 +1 to combat resolution in a tie. +1 Leadership when attempting to Rally (may not exceed 10). +1 to Combat Resolution; Standard can be captured if unit Flees. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. +2 Strength when on foot; +1 Strength if mounted. Always strikes last unless charging. Two-handed. 5+ Armour save. 9 3 5+ 4/6 4 1 5 1 1 3 2 Unit is Immune to Fear and Terror. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 4+ Armor Save +1 Armour save bonus. 2 9 3 3+/2+ 4 4 1 5 1 2 3 +1 to combat resolution in a tie. +1 Leadership when attempting to Rally (may not exceed 10). +1 to Combat Resolution; Standard can be captured if unit Flees. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 4+ Armor Save +1 Armour save bonus. 9 3 3+/2+ 4 4 1 5 1 1 3 2 The unit counts as double its actual Unit Strength. +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 6+ Armour save. 2 9 3 6+ 3 4 4 1 1 3 +1 Armour save bonus in combat when on foot and fighting with a shield; no effect if mounted. 6+ Armour save. 2 9 3 6+ 3 4 4 1 1 3 2 9 4+ 4 5 3 4 3 2 2 9 4+ 4 5 3 4 3 2
