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.
Related
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.
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?
<Fruits>
<FruitName>Amla</FruitName>
<FruitPrice>10 US DOLLARS</FruitPrice>
<Origin>
<Country>INDIA</Country>
<NativeName>GOOSEBERRY</NativeName>
<Availability>PLENTY</Availability>
</Origin>
<OtherInfo>
<FiberPercentage>1.11</FiberPercentage>
<MagnesiumPercentage>0.02</MagnesiumPercentage>
</OtherInfo>
While De serializing the above XML structure, I use something like,
Xml
XmlElement("FruitsList")]
public List<Fruits> FruitsImport { get; set; }
In Fruits Class, I have something like:
[XmlAnyElement]
public List<XmlElement> FruitElements { get; set; }
[XmlElement("Origin")]
public List<XmlElement> FruitOrigin { get; set; }
[XmlElement("OtherInfo")]
public List<XmlElement> OtherInfo { get; set; }
FruitElement retrieves the FruitName and FruitPrice.
FruitOrigin retrives Country Info alone.
OtherInfo retrives FiberPercentage alone.
Any ideas on how to get all the info under <Origin> and <OtherInfo> tags ?
Because you have elements nested in both <origin> and <otherinfo> tags, you need to define a class for them as well when performing deserialization.
[XmlElement("Origin")]
public List<Origins> FruitOrigin { get; set; }
You would define the origin class the same way as you did for fruit class.
(The skeleton of Origin class would be something as below:
[Serializable]
public class Origin
{
[XmlAnyElement]
public List<XmlElement> OriginElements { get; set; }
}
)
The best way is to write XSD schema for the XML and generate class from XSD schema using XSD.exe, this way you can validate that always XML and class matches to XSD and never have issue with Serialization/ Deserialization.
You can create batch file like below to generate class from xsd schema:
del Configuration.AutoGenerated.cs
"%ProgramFiles%\Microsoft SDKs\Windows\v6.0A\bin\xsd" Test.Configuration.xsd /c /n:Test.Configuration
rename Test_Configuration.cs Configuration.AutoGenerated.cs
pause
You can see more usage examples at above link for XSD.exe.
It will generate partial classes so you can easily extend it further if required.
I have an MVC website that, when you click a button, will use Get method to grab xml data from another website. I need to then display part of this XML in my webpage.
My current approach is to deserialize the XML into objects, and pass the objects into the View, which will then grab the appropriate data.
My problem is that my classes don't match the XML data entirely (it doesn't have every element/attribute/etc). The data is too long, with too many elements and attributes, so I don't want to write everything to the classes. And I couldn't create classes from the XML data using XSD.exe because of some error in the data (though the xml data works fine when my webpage is reading it).
Is there a more efficient way of doing this?
Read in this link that IXmlSerializable might be away, although the comments also noted some problems with it. And it seems like it might be quite complicated.
How to deserialize only part of an XML document in C#
Your help is much appreciated. Thanks!
Use framework to consume Atom feeds. See the following: System.ServiceModel.Syndication namespace - msdn.microsoft.com/en-us/library/system.servicemodel.syndication.aspx
Instead of directly deserializing the atom feed xml into objects first load the xml into the XDocument object and then query the XDocument object using XLinq and create the necessary ViewModel that need to be passed to the view.
For ex.
View Model
public class FeedViewModel
{
..
public FeedItem[] FeedItems { get; set; }
}
public class FeedItem
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
}
In your action
var feedDocument = XDocument.Load(feedUrl);
var feedItems = feedDocument.Descendants("item")
orderby DateTime.Parse(feed.Element("pubDate").Value) descending
select new FeedItem
{
Title = feed.Element("title").Value,
Description = feed.Element("description").Value,
Date = DateTime.Parse(feed.Element("pubDate").Value)
}.ToArray();
return View(new FeedViewModel{ FeedItems = feedItems });
http://deepumi.wordpress.com/2010/02/21/how-to-consume-an-atom-rss-feed-using-asp-net-c-with-linq/
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.