Convert embedded XML to List<T> within a Repository - c#

I have a situation where in I have to read my master data from XML files.
Hence I have created a Repository which looks like this.
public class XmlReadRepository<T> : IReadRepository<T> where T : class, new()
{
private IEnumerable<T> _data { get; set; }
private IQueryable<T> _query { get; set; }
public XmlReadRepository()
{
Type t = typeof(T);
//Load _data from xml
}
public IQueryable<T> All()
{
return _query;
}
public IQueryable<T> Get(System.Linq.Expressions.Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "")
{
throw new NotImplementedException();
}
}
I have exported all my SQL database data into XML file using below SQL query
SELECT *
FROM Company
FOR XML RAW, ROOT('Company')
Whose outputs comes as below
<Company>
<row Id="1" Name="ABC" StartDate="2000-03-01" />
<row Id="2" Name="XYZ" StartDate="2001-13-11" />
</Company>
The xml is physically saved to a file and is embedded as a resource.
Now I am looking for some fast way to serialize the xml data into list.
I have tried loading the xml file with stream and then using reflection created objects by iterating through the XML. Is there any better way by which I can serialize the xml data to my C# object.
Also please share your inputs on whether is it good to have xml as an embedded resource as the size of each xml can be around 8MB and there are 5 such XMLs.

You can turn my code into a function
public class Row
{
private static XmlTextReader reader = null;
public int Id { get; set; }
public string name { get; set; }
public DateTime startDate { get; set; }
public Row() { }
public Row(TextReader sReader)
{
reader = new XmlTextReader(sReader); //can be filename instead of stringreader
}
public Row Get(string elementName)
{
Row results = null;
if (!reader.EOF)
{
if (reader.Name != elementName)
{
reader.ReadToFollowing(elementName);
}
if (!reader.EOF)
{
XElement newRow = (XElement)XElement.ReadFrom(reader);
results = new Row() { Id = (int)newRow.Attribute("Id"), name = (string)newRow.Attribute("Name"), startDate = (DateTime)newRow.Attribute("StartDate") };
}
}
return results;
}
}​

Use xml linq like below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<Company>" +
"<row Id=\"1\" Name=\"ABC\" StartDate=\"2000-03-01\" />" +
"<row Id=\"2\" Name=\"XYZ\" StartDate=\"2001-13-11\" />" +
"</Company>";
XDocument doc = XDocument.Parse(xml); // use Load to read from file
var rows = doc.Descendants("row").Select(x => new
{
id = (int)x.Attribute("Id"),
name = (string)x.Attribute("Name"),
startDate = (DateTime)x.Attribute("StartDate")
}).ToList();
//using xmltextreader
List<Row> rows2 = new List<Row>();
StringReader sReader = new StringReader(xml);
XmlTextReader reader = new XmlTextReader(sReader); //can be filename instead of stringreader
while(!reader.EOF)
{
if (reader.Name != "row")
{
reader.ReadToFollowing("row");
}
if (!reader.EOF)
{
XElement newRow = (XElement)XElement.ReadFrom(reader);
rows2.Add(new Row() { Id = (int)newRow.Attribute("Id"), name = (string)newRow.Attribute("Name"), startDate = (DateTime)newRow.Attribute("StartDate") });
}
}
}
}
public class Row
{
public int Id { get; set; }
public string name { get; set; }
public DateTime startDate { get; set; }
}
}
​

Related

file xml inside multiple xml in one line

I have a file .xml inside multiple xml in one line.
How can I read this file and convert to object?
I tried with this code it works if there is only one.
Please help and thank you all
[XmlRoot(ElementName = "DepartmentMaster")]
public class DepartmentMaster
{
[XmlElement(ElementName = "DepartmentId")]
public int DepartmentId { get; set; }
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Description")]
public string Description { get; set; }
[XmlElement(ElementName = "test")]
public int Test { get; set; }
}
//string xml = "<DepartmentMaster><DepartmentId>267854</DepartmentId><Name>Purchase</Name><Description>Purchase Department</Description><test>1</test></DepartmentMaster>";
string xml = "<DepartmentMaster><DepartmentId>267854</DepartmentId><Name>Purchase</Name><Description>Purchase Department</Description><test>1</test></DepartmentMaster><DepartmentMaster><DepartmentId>267855</DepartmentId><Name>Purchase5</Name><Description>Purchase Department5</Description><test>5</test></DepartmentMaster>";
using (TextReader reader = new StringReader(xml))
{
System.Xml.Serialization.XmlSerializer deserializer = new System.Xml.Serialization.XmlSerializer(typeof(DepartmentMaster));
var model = (DepartmentMaster)deserializer.Deserialize(reader);
}
image from the database
image from the database
Here it is two approaches below.
The first is using setting to accept XML data with multiple root elements (ConformanceLevel.Fragment).
private static IList<DepartmentMaster> DeserializeFragment(string xml)
{
var settings = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
XmlReader reader = XmlReader.Create(new MemoryStream(Encoding.ASCII.GetBytes(xml)), settings);
var serializer = new XmlSerializer(typeof(DepartmentMaster));
var list = new List<DepartmentMaster>();
while (serializer.Deserialize(reader) is DepartmentMaster element)
{
list.Add(element);
}
return list;
}
And the second by adding a root element to deserialize a well-formed XML document.
public class DepartmentMasters
{
[XmlElement("DepartmentMaster")]
public List<DepartmentMaster> Items;
}
private static DepartmentMasters DeserializeWellFormedXML(string xml)
{
var text = #"<?xml version=""1.0""?><DepartmentMasters>" + xml + "</DepartmentMasters>";
var serializer = new XmlSerializer(typeof(DepartmentMasters));
return (DepartmentMasters)serializer.Deserialize(new StringReader(text));
}

Creating a XML file from a database with a model C#

So I need to create a method that makes an XML file from a database, I have already written the stored procedures that get the information from a database for the XML now I only need to write the part where I convert my database to a XML file using the properties of another class that I have written as nodes.
public string CreateXML(Object YourClassObject){
XmlDocument xmlDoc =new XmlDocument(); //Represents an XML document,
// Initializes a new instance of the XmlDocument class.
XmlSerializer xmlSerializer = new XmlSerializer(YourClassObject.GetType());
// Creates a stream whose backing store is memory.
using (MemoryStream xmlStream =new MemoryStream())
{
xmlSerializer.Serialize(xmlStream, YourClassObject);
xmlStream.Position = 0;
//Loads the XML document from the specified string.
xmlDoc.Load(xmlStream);
return xmlDoc.InnerXml;
}
}
This is some code I found online I think I can use for serializing my model, but i'm accessing the database over an event that I created (I'll provide the code tomorrow when I get to work). Anyway I'm accesing the database in the event like the following e.DataTable. Any ideas anybody?
My model looks like the following:
public class DataModel
{
string Sifra {get; set;}
public string Naziv {get; set;}
public string JM {get; set;}
public int Kolicina {get; set;}
public float Cena_x0020_vp {get; set;}
public float Cena_x0020_mp {get; set;}
public float Cena_x0020_bod {get; set;}
public string Slika {get; set;}
public string Grupa {get; set;}
}
This is a sample of how my generated XML should look like.
<?xml version="1.0" encoding="UTF-8"?>
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2019-04-17T19:13:54">
<row>
<Sifra>ADA110-100</Sifra>
<Naziv_x0020_artikla>Adapter 220/110VAC 100W</Naziv_x0020_artikla>
<JM>kom</JM>
<Kolicina>1</Kolicina>
<Cena_x0020_vp>2683.33</Cena_x0020_vp>
<Cena_x0020_mp>3220</Cena_x0020_mp>
<Cena_x0020_bod>28</Cena_x0020_bod>
<Slika1> ada110v.jpg</Slika1>
<Grupa>Adateri 110V AC</Grupa>
</row>
Problem solved:
private void CreateXML(DataTable dataTable)
{
var list = new List<Row>();
XmlSerializer writer = new XmlSerializer(typeof(List<Row>));
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ExportZaWeb.xml";
FileStream file = File.Create(path);
foreach (DataRow row in dataTable.Rows)
{
Row r = new Row();
r.Naziv = row["Naziv Artikla"].ToString();
r.JM = row["JM"].ToString();
r.Kolicina = row["Kolicina"].ToString();
r.Cena_x0020_vp = row["Cena vp"].ToString();
r.Cena_x0020_mp = row["Cena mp"].ToString();
r.Cena_x0020_bod = row["Cena bod"].ToString();
r.Slika = row["Slika1"].ToString();
r.Grupa = row["Grupa"].ToString();
list.Add(r);
}
writer.Serialize(file, list);
file.Close();
}
Why not let the stored procedure return the xml for you. The query in the stored procedure would lool something like this:
SELECT Sifra, Naziv, JM, Kolicina, Cena_x0020_vp, Cena_x0020_mp, Cena_x0020_bod, Slika, Grupa
FROM DataModel
FOR XML AUTO
Create a method which takes in a list or IEnumerable object of the Models and returns a string containing the XML (untested, but should get you started), this is assuming you already have the database data in usable objects:
public string GetXmlForModels(IEnumerable<DataModel> dataModels)
{
//Assume a list of DataModels is in dataModels of type IEnumerable<DataModel>
var doc = new XmlDocument();
foreach (var model in dataModels)
{
var row = (XmlElement)doc.AppendChild(doc.CreateElement("row"));
row.SetAttribute("xmlns:od", "urn:schemas-microsoft-com:officedat");
row.SetAttribute("generated", DateTime.Now.ToString("yy-MM-ddTHH:mm:ss"));
var sifraElement = doc.CreateElement("Sifra");
sifraElement.InnerText = model.Sifra;
row.AppendChild(sifraElement);
//Repeat top 3 lines for each element ...
doc.AppendChild(row);
}
return doc.OuterXml;
}
Use XML Serializer :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication110
{
class Program
{
const string INPUT_FILENAME = #"c:\temp\test.xml";
const string OUTPUT_FILENAME = #"c:\temp\test1.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(INPUT_FILENAME);
string xml = reader.ToString();
XmlSerializer serializer = new XmlSerializer(typeof(DataRoot));
DataRoot root = (DataRoot)serializer.Deserialize(reader);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(OUTPUT_FILENAME,settings);
serializer.Serialize(writer, root);
}
}
[XmlRoot(ElementName = "dataroot", Namespace = "")]
public class DataRoot
{
[XmlElement(ElementName = "row", Namespace = "")]
public List<DataModel> rows { get; set; }
}
[XmlRoot(ElementName = "row", Namespace = "")]
public class DataModel
{
string Sifra { get; set; }
public string Naziv { get; set; }
public string JM { get; set; }
public int Kolicina { get; set; }
public float Cena_x0020_vp { get; set; }
public float Cena_x0020_mp { get; set; }
public float Cena_x0020_bod { get; set; }
public string Slika { get; set; }
public string Grupa { get; set; }
}
}

Selecting XmlNode's Child Nodes based on Tag

I'm trying to parse this XML Document:
<MPD>
<Period duration="PT0H3M1.63S" start="PT0S">
<AdaptationSet>
<ContentComponent contentType="video" id="1" />
<Representation bandwidth="4190760" codecs="avc1.640028" height="1080" id="1" mimeType="video/mp4" width="1920">
<BaseURL>car-20120827-89.mp4</BaseURL>
</Representation>
<Representation bandwidth="2073921" codecs="avc1.4d401f" height="720" id="2" mimeType="video/mp4" width="1280">
<BaseURL>car-20120827-88.mp4</BaseURL>
</Representation>
</AdaptationSet>
<AdaptationSet>
<ContentComponent contentType="audio" id="2" />
<Representation bandwidth="127236" codecs="mp4a.40.2" id="6" mimeType="audio/mp4" numChannels="2" sampleRate="44100">
<BaseURL>car-20120827-8c.mp4</BaseURL>
</Representation>
<Representation bandwidth="255236" codecs="mp4a.40.2" id="7" mimeType="audio/mp4" numChannels="2" sampleRate="44100">
<BaseURL>car-20120827-8d.mp4</BaseURL>
</Representation>
</AdaptationSet>
</Period>
</MPD>
using this C# code:
var rootDoc = new XmlDocument();
rootDoc.LoadXml(xmlString); // the one from above
var adaptationSets = rootDoc.GetElementsByTagName("AdaptationSet");
if (adaptationSets.Count > 0)
foreach (XmlNode adaptionSet in adaptationSets) // Loop through AdaptionSets
{
// Get the one Node in this AdaptionSet with the ContentComponent-Tag
var contentComponent = adaptionSet.SelectSingleNode("ContentComponent");
if (contentComponent != null)
{
// parse attributes
}
// Get All Nodes in this AdaptionSet with the Representation-Tag
var representations = adaptionSet.SelectNodes("Representation");
if(representations?.Count > 0)
foreach (XmlNode representation in representations)
{
// parse attributes of XmlNode
}
}
It all works except for the XPath queries. I tried a lot of variations with leading "/", "//", "./" and without any leading characters, but it just won't work. What am I doing wrong? I'm not using XPath on a regular basis and I couldn't find anything more than the leading characters I mentioned. Because I've seen it on a lot of other answers on this website I feel like I should mention that I'm explicitly looking for the XPath that will help me solve this, not some Linq variation or an entirely different approach.
Any help is greatly appreciated. Thanks in advance!
I think this solves your problem:
var rootDoc = new XmlDocument();
rootDoc.LoadXml(xmlString); // the one from above
var adaptationSets = rootDoc.SelectNodes("//AdaptationSet");
if (adaptationSets.Count > 0)
foreach (XmlNode adaptionSet in adaptationSets) // Loop through AdaptionSets
{
// Get the one Node in this AdaptionSet with the ContentComponent-Tag
var contentComponent = adaptionSet.SelectSingleNode("./ContentComponent");
if (contentComponent != null)
{
// parse attributes
}
// Get All Nodes in this AdaptionSet with the Representation-Tag
var representations = adaptionSet.SelectNodes("./Representation");
if (representations?.Count > 0)
foreach (XmlNode representation in representations)
{
// parse attributes of XmlNode
}
}
Try using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement period = doc.Descendants("Period").FirstOrDefault();
MPD mpd = new MPD();
mpd.duration = (string)period.Attribute("duration");
mpd.start = (string)period.Attribute("start");
mpd.adaptions = period.Elements("AdaptationSet").Select(x => new Adaption() {
contentType = (string)x.Element("ContentComponent").Attribute("contentType"),
id = (int)x.Element("ContentComponent").Attribute("id"),
representations = x.Elements("Representation").Select(y => new Representation() {
bandwidth = (int)y.Attribute("bandwidth"),
codecs = (string)y.Attribute("codecs"),
height = (int?)y.Attribute("height"),
id = (int)y.Attribute("id"),
mimeType = (string)y.Attribute("mimeType"),
width = (int?)y.Attribute("width"),
baseURL = (string)y.Descendants("BaseURL").FirstOrDefault()
}).ToList()
}).ToList();
}
}
public class MPD
{
public string duration { get; set; }
public string start { get; set; }
public List<Adaption> adaptions { get; set; }
}
public class Adaption
{
public string contentType { get; set; }
public int id { get; set; }
public List<Representation> representations { get; set; }
}
public class Representation
{
public int bandwidth { get; set; }
public string codecs { get; set; }
public int? height { get; set; }
public int id { get; set; }
public string mimeType { get; set; }
public int? width { get; set; }
public string baseURL { get; set; }
}
}

How to do the pagination with XmlReader class c#

At present i am fetching data from xml file using LINQ but the problem is i am using XDocument to load xml file but XDocument class load xml data into memory. so if there is 10,000 data in my xml file then XDocument class will load 10,000 data into memory. so some one tell me if use read xml data with XmlReader class then it will not dump full data into memory.
At present this way i am fetching data from xml file.
My xml data look like:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Orders>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<EmployeeID>5</EmployeeID>
<OrderDate>1996-07-04T00:00:00</OrderDate>
<RequiredDate>1996-08-01T00:00:00</RequiredDate>
<ShippedDate>1996-07-16T00:00:00</ShippedDate>
<ShipVia>3</ShipVia>
<Freight>32.3800</Freight>
<ShipName>Vins et alcools Chevalier</ShipName>
<ShipAddress>59 rue de l'Abbaye</ShipAddress>
<ShipCity>Reims</ShipCity>
<ShipPostalCode>51100</ShipPostalCode>
<ShipCountry>France</ShipCountry>
</Orders>
</Root>
here i am posting code wich fetch data from xml file with order by and paging.
XDocument document = XDocument.Load(#"c:\users\documents\visual studio 2010\Projects\WindowsFormsApplication5\WindowsFormsApplication5\Orders.xml");
bool isDesc = true;
//setup basic query
var query = from r in document.Descendants("Orders")
select new
{
OrderID = r.Element("OrderID").Value,
CustomerID = r.Element("CustomerID").Value,
EmployeeID = r.Element("EmployeeID").Value,
};
//setup query result ordering,
//assume we have variable to determine ordering mode : bool isDesc = true/false
if (isDesc)
query = query.OrderByDescending(o => o.OrderID);
else
query = query.OrderBy(o => o.OrderID);
//setup pagination,
//f.e displaying result for page 2 where each page displays 100 data
var page = 1;
var pageSize = 5;
query = query.Skip(page - 1 * pageSize).Take(pageSize);
//execute the query to get the actual result
//var items = query.ToList();
dataGridView1.DataSource = query.ToList();
So some one tell me how could i use xmlreader to read data from xml file with pagination and order by clause will be there.
I got one hit but do not understand how to use it for my purpose:
using( var reader = XmlReader.Create( . . . ) )
{
reader.MoveToContent();
reader.ReadToDescendant( "book" );
// skip N <book> elements
for( int i = 0; i < N; ++i )
{
reader.Skip();
reader.ReadToNextSibling( "book" );
}
// read M <book> elements
for( int i = 0; i < M; ++i )
{
var s = reader.ReadOuterXml();
Console.WriteLine( s );
reader.ReadToNextSibling( "book" );
}
}
So please see the above code and help me to construct the code which would use xml reader to fetch paginated data.
Try this code. Your latest posting is locked so I had to answer here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
Order order = new Order();
while(reader.ReadToFollowing("Orders"))
{
string xml = reader.ReadOuterXml().Trim();
XElement element = XElement.Parse(xml);
order.Add(element);
}
order.Sort();
}
}
public class Order
{
public void Add(XElement element)
{
if (orders == null)
{
orders = new List<Order>();
}
Order newOrder = new Order();
newOrder.OrderId = int.Parse(element.Element("OrderID").Value);
newOrder.CustomerId = element.Element("CustomerID").Value;
newOrder.EmployeeId = int.Parse(element.Element("EmployeeID").Value);
newOrder.OrderDate = DateTime.Parse(element.Element("OrderDate").Value);
newOrder.RequiredDate = DateTime.Parse(element.Element("RequiredDate").Value);
newOrder.ShippedDate = DateTime.Parse(element.Element("ShippedDate").Value);
newOrder.ShipVia = int.Parse(element.Element("ShipVia").Value);
newOrder.Freight = double.Parse(element.Element("Freight").Value);
newOrder.ShipName = element.Element("ShipName").Value;
newOrder.ShipAddress = element.Element("ShipAddress").Value;
newOrder.ShipCity = element.Element("ShipCity").Value;
newOrder.ShipPostalCode = int.Parse(element.Element("ShipPostalCode").Value);
newOrder.ShipCountry = element.Element("ShipCountry").Value;
orders.Add(newOrder);
}
public void Sort()
{
orders = orders.OrderBy(x => x.OrderId).ToList();
}
public static List<Order> orders { get; set; }
public int OrderId { get; set; }
public string CustomerId { get; set; }
public int EmployeeId { get; set; }
public DateTime OrderDate { get; set; }
public DateTime RequiredDate { get; set; }
public DateTime ShippedDate { get; set; }
public int ShipVia { get; set; }
public double Freight { get; set; }
public string ShipName { get; set; }
public string ShipAddress { get; set; }
public string ShipCity { get; set; }
public int ShipPostalCode { get; set; }
public string ShipCountry { get; set; }
}
}
​

XML Serialization and iterating

I have this XML file which have 3 Words.
<synset id="n00252662" type="n">
<lex_filenum>04</lex_filenum>
<word lex_id="1">purge</word>
<word lex_id="1">purging</word>
<word lex_id="1">purgation</word>
<pointer refs="n01247647">Hypernym</pointer>
<pointer refs="v00905283" source="3" target="1">Derivationally related form</pointer>
<pointer refs="v00475647" source="2" target="1">Derivationally related form</pointer>
<pointer refs="v00475819" source="1" target="2">Derivationally related form</pointer>
<pointer refs="v00905283" source="1" target="1">Derivationally related form</pointer>
<pointer refs="n00252894">Hyponym</pointer>
<def>the act of clearing yourself (or another) from some stigma or charge</def>
</synset>
And DictionaryList.cs
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Xml;
using UnityEngine;
using System.IO;
[XmlRoot("DictionaryList")]
public class DictionaryList
{
[XmlArray("synsets")]
[XmlArrayItem("synset")]
public List<Dictionary> Dict = new List<Dictionary>();
//string filepath = Application.dataPath + "/Resources/gamedata.xml";
public static DictionaryList Load(string path)
{
var serializer = new XmlSerializer(typeof(DictionaryList));
using (var stream = new FileStream(path, FileMode.Open))
{
return serializer.Deserialize(stream) as DictionaryList;
}
}
//Loads the xml directly from the given string. Useful in combination with www.text.
public static DictionaryList LoadFromText(string text)
{
var serializer = new XmlSerializer(typeof(DictionaryList));
return serializer.Deserialize(new StringReader(text)) as DictionaryList;
}
}
Then The Dictionary.cs
using System.Xml;
using System.Xml.Serialization;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public class Dictionary
{
public string word;
public string def;
public string example;
public Dictionary()
{
}
public Dictionary(string nme, string Des)
{
word = nme;
def = Des;
}
}
In my Code, the deserializer does not Include the word purging and purgation since the word <- variable is not an Array.
I have tried to make it an array List but I am not sure if the the deserializer will even put the other words if I make an List array word to it.
Plus accessing the the List inside the list is giving me a problem. I want to know if there is an option I can take where I can access or even store the word as an array without altering the XML file.
And this is my main Dictionary file
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Linq;
using UnityEngine.UI;
public class MainDictionary : MonoBehaviour {
DictionaryList DictionaryCollectionNoun;
DictionaryList DictionaryCollectionVerb;
DictionaryList DictionaryCollectionADV;
public InputField SearchField;
public Text NameField;
public Text DetailsField;
public Text DebugText;
public Text ExampleField;
public TextAsset textAssetNoun;
public TextAsset textAssetVerb;
public TextAsset textAssetADV;
// Use this for initialization
void Start () {
//TextAsset textAsset = (TextAsset)Resources.Load("datanoun", typeof(TextAsset));
//XmlDocument xmldoc = new XmlDocument ();
//xmldoc.LoadXml ( textAsset.text );
DebugText.text = Application.dataPath;
textAssetNoun = (TextAsset)Resources.Load("datanoun");
textAssetVerb = (TextAsset)Resources.Load("dataverb");
textAssetADV = (TextAsset)Resources.Load("dataadv");
//XmlDocument xmldoc = new XmlDocument();
//xmldoc.LoadXml(textAsset.text);
//Example Psuedocode Danzee Mode;
//var xmlData = #"<DictionaryList><synsets><synset><word>test</word><def>Fun</def></synset></synsets></DictionaryList>";
DictionaryCollectionNoun = DictionaryList.LoadFromText(textAssetNoun.text);
DictionaryCollectionVerb = DictionaryList.LoadFromText(textAssetVerb.text);
DictionaryCollectionADV = DictionaryList.LoadFromText(textAssetADV.text);
//Debug.Log(Application.dataPath);
//DebugText.text = xmldoc.ToString();
}
public void ChangeSearch()
{
//Dictionary Result = new Dictionary("No Result", "No Description");
//bool nounBool = DictionaryCollectionNoun.Dict.Any(p => p.word == SearchField.text.ToLower()) ? true : false;
//bool verbBool = DictionaryCollectionVerb.Dict.Any(p => p.word == SearchField.text.ToLower()) ? true : false;
//bool advbool = DictionaryCollectionADV.Dict.Any(p => p.word == SearchField.text.ToLower()) ? true : false;
//if (nounBool)
//{
// Result = DictionaryCollectionNoun.Dict.Find(x => x.word == SearchField.text.ToLower());
//}
//else if (verbBool)
//{
// Result = DictionaryCollectionVerb.Dict.Find(x => x.word == SearchField.text.ToLower());
//}
//else if (advbool)
//{
// Result = DictionaryCollectionADV.Dict.Find(x => x.word == SearchField.text.ToLower());
//}
//NameField.text = Result.word1;
//DetailsField.text = Result.def2;
//ExampleField.text = Result.example;
}
}
Try the following:
public class Word
{
[XmlAttribute("lex_id")]
public string LexId { get; set; }
[XmlText]
public string Value { get; set; }
public override string ToString()
{
return Value;
}
public static explicit operator string(Word word)
{
if (word == null)
return null;
return word.Value;
}
}
public class SynsetPointer
{
[XmlAttribute("refs")]
public string Refs { get; set; }
[XmlAttribute("source")]
public string Source { get; set; }
[XmlAttribute("target")]
public string Target { get; set; }
[XmlText]
public string Value { get; set; }
}
[XmlRoot("synset")]
[XmlType("synset")]
public class Synset
{
public Synset()
{
this.Pointers = new List<SynsetPointer>();
this.Words = new List<Word>();
}
[XmlElement("lex_filenum")]
public int LexFilenum { get; set; }
[XmlElement("word")]
public List<Word> Words { get; set; }
[XmlIgnore]
public IEnumerable<string> WordValues { get { return (Words == null ? null : Words.Select(w => (string)w)); } }
[XmlElement("pointer")]
public List<SynsetPointer> Pointers { get; set; }
[XmlElement("def")]
public string Definition { get; set; }
}
[XmlRoot("DictionaryList")]
public class DictionaryList
{
public DictionaryList()
{
this.Dict = new List<Synset>();
}
[XmlArray("synsets")]
[XmlArrayItem("synset")]
public List<Synset> Dict { get; set; }
//string filepath = Application.dataPath + "/Resources/gamedata.xml";
public static DictionaryList Load(string path)
{
var serializer = new XmlSerializer(typeof(DictionaryList));
using (var stream = new FileStream(path, FileMode.Open))
{
return serializer.Deserialize(stream) as DictionaryList;
}
}
//Loads the xml directly from the given string. Useful in combination with www.text.
public static DictionaryList LoadFromText(string text)
{
var serializer = new XmlSerializer(typeof(DictionaryList));
return serializer.Deserialize(new StringReader(text)) as DictionaryList;
}
}
I renamed your Dictionary class to Synset for clarity, since c# already has various dictionary classes which do something different.
To read multiple word elements into an array, declare it as a List<Word> in the Synset class, then apply the [XmlElement] attribute. This tells the serializer to expect repeated occurrences of the word element rather than a nested list of elements.
This will successfully read and write XML that looks like this:
<DictionaryList>
<synsets>
<synset>
<lex_filenum>4</lex_filenum>
<word lex_id="1">purge</word>
<word lex_id="1">purging</word>
<word lex_id="1">purgation</word>
<pointer refs="n01247647">Hypernym</pointer>
<pointer refs="v00905283" source="3" target="1">Derivationally related form</pointer>
<pointer refs="v00475647" source="2" target="1">Derivationally related form</pointer>
<pointer refs="v00475819" source="1" target="2">Derivationally related form</pointer>
<pointer refs="v00905283" source="1" target="1">Derivationally related form</pointer>
<pointer refs="n00252894">Hyponym</pointer>
<def>the act of clearing yourself (or another) from some stigma or charge</def>
</synset>
</synsets>
</DictionaryList>
Update
To loop through all the text values of all the Word classes in all the Synset classes in a DictionaryList, you can do:
var testXml = #"<DictionaryList> <synsets> <synset id=""n00001740"" type=""n""> <lex_filenum>03</lex_filenum> <word lex_id=""0"">entity</word> <pointer refs=""n00001930 n00002137 n04424418"">Hyponym</pointer> <def>that which is perceived or known or inferred to have its own distinct existence (living or nonliving)</def> </synset> </synsets> </DictionaryList>";
var dict = DictionaryList.LoadFromText(testXml);
foreach (var synSet in dict.Dict)
{
var words = synSet.WordValues.ToList();
var word0 = (words.Count > 0 ? words[0] : null);
var word2 = (words.Count > 2 ? words[2] : null);
// Do something with the words.
}
Update 2
To search for a Synset containing a given word, you can do:
var word = "entity";
var Results = dict.Dict.Where(s => s.WordValues.Any(w => w == word)); // Find all synsets containing the word "entity"
var Result = dict.Dict.FirstOrDefault(s => s.WordValues.Any(w => w == word)); // Find the first synsets containing the word "entity"

Categories

Resources