I've got a working program that turns XML into a XmlObject. The object can then be accessed using getName(), getValue(), and getChild(). The code works but I'm looking for recommendations. I couldn't find anything built into c# that creates an object from XML. I'm currently learning by doing games in Unity so hopefully the code isn't too awful.
The static class for creating an XmlObject
namespace XmlToObject
{
using System.Collections.Generic;
using System.Xml;
using System.IO;
using UnityEngine;
/// XmlObjectCreator turns xml into an XmlObject
public static class XmlObjectCreator
{
/// Generates the xml object.
public static XmlObject generateXmlObject (TextAsset xmlTextFile, string nameOfFirstTag)
{
//load the xml document
XmlDocument xmlDoc = new XmlDocument ();
xmlDoc.Load (new StringReader (xmlTextFile.text));
//Navigate to the first tag
XmlNode firstNode = xmlDoc.SelectSingleNode ("//" + nameOfFirstTag);
//Return the built object
return recursiveBuildXmlObject (firstNode);
}
/// Recursivly builds an xml object.
private static XmlObject recursiveBuildXmlObject (XmlNode startNode)
{
//Create the buildObject
XmlObject buildObject = new XmlObject ();
//Set the name and value
buildObject.setName (startNode.Name);
buildObject.setValue (startNode.InnerText);
//Add child nodes to subList if they exist
foreach (XmlNode child in startNode.ChildNodes) {
buildObject.add (recursiveBuildXmlObject (child));
}
//Once children are done
return buildObject;
}
}
}
The XmlObject is what is actually used for accessing the data taken from the XML document.
namespace XmlToObject
{
using System.Collections.Generic;
/// Xml object is the actual object used for navigating the data.
public sealed class XmlObject
{
private string name;
private string value;
private List<XmlObject> subList;
/// Initializes a new instance of the XmlObject class.
public XmlObject ()
{
subList = new List<XmlObject> ();
value = null;
}
/// Add the specified inputXmlObject.
public void add (XmlObject inputXmlObject)
{
subList.Add (inputXmlObject);
}
/// Gets a xml child by name.
public XmlObject getChild (string name)
{
foreach (XmlObject child in subList) {
if (name.Equals (child.getName ())) {
return child;
}
}
throw new System.ArgumentException ("Child with name: " + name + " does not exist.");
}
//Setters and getters for fields: name, value
public string getName ()
{
return name;
}
public void setName (string newName)
{
name = newName;
}
public string getValue ()
{
return value;
}
public void setValue (string newValue)
{
value = newValue;
}
}
}
I've seen lots of code that deals with known XML structures, but few examples where the XML structure is not predefined/known. I'm sure that there is a better way to do what this code does, I'm just not sure what it is.
-
1\$\begingroup\$ @t3chb0t Okay I added them back in. \$\endgroup\$Striar– Striar2017年06月28日 18:32:56 +00:00Commented Jun 28, 2017 at 18:32
1 Answer 1
It is a good Idea to create a generic object model that may represent an XML document. Therefore, the .Net Framework already contains such models: XmlDocument and XDocument.
I would really suggest to use them.
Some comments to your code:
- Methods and properties usually start with a capital letter in C#.
- The method
getChild
throws an exception if no element was found. Consider to return null instead because it is not an exceptional use case and returning null is more flexible. - The field
subList
could be read-only. - C# has the concept of Properties which should be used instead of
get*
andset*
methods
buildObject.setName(startNode.Name); buildObject.setValue(startNode.InnerText);
The code above does not produce the expected result because InnerText is not just the inner text of the current node but the text of the current and all sub nodes. The following XML for example:
<xml>
<test>
<blub>foo</blub>
<blub>bar</blub>
</test>
</xml>
Produces something like:
XmlObject(Name: xml, Value: foobar)
XmlObject(Name: test, Value foobar)
XmlObject(Name: blub, Value foo)
XmlObject(Name: blub, Value bar)