Reputation: 793
hey i am having hard time to "rebuild"(read) my object. my structure is very simple:
groupName<--object
name<--prop
addres<--prop
phone<--prop
how can i rebuild it back to the same structure?
here is how i am writing it to xml
public override void Save(PhoneBook pb)
{
using (XmlWriter writer = XmlWriter.Create(path))
{
writer.WriteStartDocument();
writer.WriteStartElement("Group");
foreach (PhoneBookGroup group in pb.Items)
{
writer.WriteStartElement("GroupName");
writer.WriteElementString("GroupName", group.GroupName.ToString());
foreach (Contect contect in group.Items)
{
writer.WriteStartElement("Addres", contect.Addres.ToString());
writer.WriteStartElement("Number", contect.Number.ToString());
writer.WriteStartElement("Name", contect.Name.ToString());
}
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndDocument();
}
}
Upvotes: 1
Views: 2100
Reputation: 48106
Use an XmlSerializer
, certainly for a first version since it'll be trivial to code. If your boss wants it differently after seeing how much simpler and less error-prone the serialization version is, you should try to convince him otherwise - part of work isn't just doing what your told, but at least giving honest advice. Unless this is supposed to be a learning experience, your boss is wrong - that's fine and normal, but you should at least try to save time and money before doing as he says. He may just not be aware of the alternatives.
The problems with the manual approach are highlighted by the fact that your code sample is buggy - you probably meant writer.WriteElementString("Number",...
rather than WriteStartElement("Number",...
. It's much much safer and simpler to use a more structured approach.
If you really need to read raw xml, I'd recommend using the XDocument
class over an XmlReader
to read your document and linq to xml to extract the relevant bits. That's still simpler than an XmlReader
, while retaining the full flexibility of hand-written code (it's just a little slower). If you insist on an XmlReader
solution (note that there's no technical reason for this), then you should try and write your own first - include your attempt in your question so we can see what you've tried.
Upvotes: 1
Reputation: 309
Having looked at your xml output I would seriously look into changing your schema as the output of your Save function creates very strangely structured xml which i think is the reason you are struggling to rebuild it. The current output would look something like this:
<?xml version="1.0" encoding="utf-8"?>
<Group>
<GroupName>
<GroupName>groupName</GroupName>
<Addres xmlns="addy">
<Number xmlns="0123456789">
<Name xmlns="Henry">
<Addres xmlns="address2">
<Number xmlns="9876543210">
<Name xmlns="Dave" />
<GroupName>
<GroupName>secondGroup</GroupName>
<Addres xmlns="fleet">
<Number xmlns="0123456789">
<Name xmlns="Me" />
</Number>
</Addres>
</GroupName>
</Number>
</Addres>
</Name>
</Number>
</Addres>
</GroupName>
</Group>
Having said that the resultant xml is not unprocessable and can be read back into the object using the method below. The only thing I have assumed from your Save code is that there is some way of getting from a string to a GroupName object (since you are using the ToString method to get the value into the xml). In my test I implemented the object with an implicit conversion operator as you can see below.
class GroupName
{
public string Name { get; set; }
public override string ToString()
{
return this.Name;
}
// Specific conversion from string to GroupName object
public static implicit operator GroupName(string s)
{
return new GroupName() { Name = s };
}
}
public PhoneBook Rebuild()
{
using (XmlReader reader = XmlReader.Create(path))
{
// read to the start of the xml
reader.MoveToContent();
// create the return object
PhoneBook returnObject = new PhoneBook();
returnObject.Items = new List<PhoneBookGroup>();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
// read each GroupName Node as a separate node collection
if (reader.Name == "GroupName")
{
// This is the root node of the groups
PhoneBookGroup grp = null;
Contact currentContact = null;
// loop the reader from this starting node
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "GroupName":
if (grp == null)
{
grp = new PhoneBookGroup();
returnObject.Items.Add(grp);
// must implement an implicit operator between string and GroupName object
grp.Name = (GroupName)reader.ReadElementString();
}
else
{
// start of a new group, so null what we have so far and start again
grp = null;
}
break;
case "Addres":
// Address is the start node for a contact so create a new contact and start filling it
currentContact = new Contact();
if (grp.Items == null)
{
grp.Items = new List<Contact>();
}
grp.Items.Add(currentContact);
// due to the way the xml is being written the value is held as the namespace !!!
currentContact.Address = reader.NamespaceURI;
break;
case "Number":
// due to the way the xml is being written the value is held as the namespace !!!
currentContact.Phone = reader.NamespaceURI;
break;
case "Name":
// due to the way the xml is being written the value is held as the namespace !!!
currentContact.Name = reader.NamespaceURI;
break;
default:
break;
}
}
}
}
}
}
return returnObject;
}
Upvotes: 1