Deserialize unknown section into List or Dictionary - c#

I have the following XML file:
<Error>0</Error>
<Description>1</Description>
<Document>
<ObjectID>06098INF1761320</ObjectID>
<ced>109340336</ced>
<abstract>DAVID STEVENSON</abstract>
<ced_a />
<NAM_REC />
<ced_ap2 />
</Document>
So I deserialize it on C# (4.0) with this objects structure:
[XmlElement("Error")]
public string Error { get; set; }
[XmlElement("Description")]
public string Description { get; set; }
[XmlElement("Document")]
public List<EDocument> LstDocument { get; set; }
So here's my issue: the element "Document" has unknown sub-elements: ObjectID, ced, etc., is there a way that I can deserialize those unknows elements into a List, Array, Dictionary or something to iterate with (something like this, it DOESN'T have to be exactly like this, I'm just guessing):
object.LstDocument[0].ListDocument.name; //to get the name
object.LstDocument[0].ListDocument.value; //to get the value
Any help would be appreciated.
EDIT 1:
To add some extra clarification to my question:
The child nodes under "Document" element are unknown because they are variable, with this I mean that at a moment I could have "ObjectID" and "ced", in other moment they could be "ced","ABC", etc. I'm not sure which elements came there as child nodes, all I know is that they are elements (not attributes) and that they don't have any child-nodes inside them.

Related

Change the way how list is serialized into XML

So, I have a class with a list of objects like this:
public int SourceId { get; set; }
public int TargetId { get; set; }
public List<ExtraParameter> ExtraParameters { get; }
Then, when it is serialized into XML file, the output is like this:
<Connection>
<SourceId>0</SourceId>
<TargetId>1</TargetId>
<ExtraParameters>
<ExtraParameter>
<Input>0</Input>
<Output>1</Output>
<Enabled>true</Enabled>
</ExtraParameter>
<ExtraParameter>
<Input>1</Input>
<Output>0</Output>
<Enabled>true</Enabled>
</ExtraParameter>
</ExtraParameters>
</Connection>
But I need to serialize this array of elements (ExtraParameter) using C#'s XmlSerializer into this form:
<Connection>
<SourceId>0</SourceId>
<TargetId>1</TargetId>
<ExtraParameter>
<Input>0</Input>
<Output>1</Output>
<Enabled>true</Enabled>
</ExtraParameter>
<ExtraParameter>
<Input>1</Input>
<Output>0</Output>
<Enabled>true</Enabled>
</ExtraParameter>
</Connection>
So in other words, can I somehow just list the items in that ExtraParameters-list without having that list in this hierarchy? So it does look like objects in the ExtraParameters are just listed at the end of the TargetID-node.
edit: Yes, I know, this kinda breaks the structure, but this xml file is then deserialized by the next program correctly, and I don't have control over that.
You can do this by adding the XmlElement attribute to the relevant property. Per the docs:
If you apply the XmlElementAttribute to a field or property that returns an array, the items in the array are encoded as a sequence of XML elements.
[XmlElement("ExtraParameter")]
public List<ExtraParameter> ExtraParameters { get; }
You could also change the property name rather than adding a value for ElementName to the attribute.
See this fiddle for a working demo.

Comparing two xml files c#

I've got two XML files and I want to compare in a C# application. I am using XDocument and I want to load both XML files (which have static filenames and directories) and search and append an entry based on matching values.
One of my XML files contains the following structure as shown below:
<Code>0000890</Code>
<Device_Name>Device1</Device_Name>
<Time>11:06:18.836 </Time> </body>
The second XML file has a structure like this:
<ID>0000890</ID>
<FirstName>John</FirstName>
<LastName>Doe</LastName> </body>
I want to read both files and match records where the ID and Code are the same but also append the first XML files with the additional details from the second XML file. So in matching cases id end up with:
<ID>0000890</ID>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Device_Name>Device1</Device_Name>
<Time>11:06:18.836 </Time> </body>
Should i use a foreach loop and step through all the entries or what is the best approach?
Any help would be greatly appreciated.
Thank you
Whenever I have to work with xml, I'd rather deserialize everything into objects so I can handle them in a type safe fashion.
In your case i would have this:
public class Item {
public Int32 ID { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String DeviceName { get; set; }
public TimeSpan Time { get; set; }
public Item(XElement xElement) {
Load(xElement);
}
public void Load(XElement xElement) {
// your code to grab values goes here
}
public XElement ToXElement() {
// your code to create the xml representation goes here
}
}
Then I'd just grab all the relevant xml elements from your file and feed them into the constructors. You can use the ID property as the Key in a Dictionary<Int32, Item> and use Load(XElement) to update more data from other xml elements so that it merges multiple data sets.
Then use ToXElement() to recreate the desired xml file with all your data.
Update: Also be sure to use XmlConvert when serializing and deserializing your values.

Xml mixed content tree structure

I'm making a xml parser for a purpose of challenge. Basically a xml node looks like this:
public struct XmlTag : IXmlTag
{
public IXmlText Name { get; }
public List<IXmlTag> Children { get; }
public Attributes Attributes { get; }
public IXmlText Content { get; }
}
IXmlText is something, that points into a place in char array.
It worked for some relatively simple xml:
<tag>
<otherTag/>
</tag>
<tag>String</tag>
But it doesn't work like that for xml
<letter>
Dear Mr.<name>John Smith</name>.
Your order <orderid>1032</orderid>
will be shipped on <shipdate>2001-07-13</shipdate>.
</letter>
because the tree structure is not suited to contain mixed content, text and other tags.
My question is which tree structure will be good enough to hold both simple text and other text, preserving the exact order of elements?

Include raw XML when deserializing XML

I have the following XML and classes that are being serialized from it:
<Alerts>
<io id="1">
<name>Foo</name>
<status>Active</status>
</io>
<io id="2">
<name>Bar</name>
<status>Inactive</status>
</io>
</Alerts>
[XmlRoot("Alerts")]
[Serializable]
public class Alerts
{
[XmlElement("io")]
public List<Alert> { get; set; }
}
public class Alert
{
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("status")]
public string Status { get; set; }
}
What I require is a property in my Alert class, that upon deserialization contains the XML of its node. For example, after deserializing the provided XML, I end up with a list of 2 Alert objects. I would need the first alert to have a property that contains this as a string:
<io id="1">
<name>Foo</name>
<status>Active</status>
</io>
Any ideas how I can achieve this?
I think the only way to actually accomplish this is to have a string property, and then in your xml replace the xml reserved characters with entity character references so it doesn't get serialized as xml. So your xml would look something like:
<io id="1">
<name>Foo</name>
<status>Active</status>
<innerAlert>
<io id="3"><name>FooBar</name><status>Inactive</status><innerAlert></innerAlert></io>
</innerAlert>
I still keep going back to my comment and thinking that you might be better off adding a property of type Alert or IEnumerable to your Alert class and let the tree deserialize out all the way down, but maybe that's just not an option to you.

Use the type's root name when serializing collection items

Just a contrived example but I have some classes that I want to control the names of when serialized.
[XmlRoot("item")]
public class ItemWrapper
{
[XmlArray("parts")]
public List<PartWrapper> Parts { get; set; }
}
[XmlRoot("part")]
public class PartWrapper
{
[XmlAttribute("name")]
public string Name { get; set; }
}
Now when I serialize an ItemWrapper that has some Parts, I was expecting each of the PartWrapper items to be serialized using the root name ("part") but it instead uses the type's name (what it would use by default if the XmlRootAttribute wasn't specified).
<item>
<parts>
<PartWrapper name="foo" />
<PartWrapper name="bar" />
</parts>
</item>
Now I know to fix this to get what I want is to add the XmlArrayItemAttribute to the Parts property to specify the name of each of the items but I feel it's redundant. I just wanted to use the name of the type's root as I specified.
[XmlRoot("item")]
public class Item
{
[XmlArray("parts")]
[XmlArrayItem("part", Type=typeof(PartWrapper))]
public List<PartWrapper> Parts { get; set; }
}
Is there a way that I can tell the serializer that I want to use the root name for the collection items? If so, how?
Why wouldn't it just use the root name? Any good reason why it shouldn't?
It was my understanding that the XmlRootAttribute allowed you to name the element exactly like an XmlElementAttribute does, only it had to be applied to the class. I guess I'm mistaken.
From the documentation, it seems that XmlRootAttribute is used only when that element is the root (which is why it works for "item" in your case):
Controls XML serialization of the attribute target as an XML root element
- MSDN
It seems to me like perhaps you want XmlTypeAttribute for things that are not root.

Categories

Resources