I have created a XML class using XSD2Code from my XML Schema. The class having a method SaveToFile. So when I am trying to add new elements and save it to the XML file it overwrites the entire content.
Does anyone have idea how to insert elements(append to the XML) to the XML file via Serialization.
eg:
<?xml version="1.0" encoding="utf-8"?>
<root>
<element>content1</element>
</root>
If this is the XML file I need to add an element and the resulting should come as like below using Serialization.
<?xml version="1.0" encoding="utf-8"?>
<root>
<element>content1</element>
<element>content2</element>
</root>
Your request would seem to be resolvable by adding another item into your List collection.
MyTypeFromXmlSchema myType = new MyTypeFromXmlSchema();
myType.MyElementItems = new List<MyElementItem>();
myType.MyElementItems.Add { new MyElementItem { value = "value1" } };
myType.MyElementItems.Add { new MyElementItem { value = "value2" } };
Then serialize type using XmlSerializer.
Related
I want a serialize a set of attributes all together to an XML file in a loop that runs. This loop runs within a set of folders . According to my Current implementation It only shows the last set of Attributes.
Here is my Current code ,
Student obj = JsonConvert.DeserializeObject < StudentModel (File.ReadAllText(file));
string Name = studentModel.name;
string number = studentModel.number;
string testPath = rootDirectory;
XmlSerializer serializer = new XmlSerializer(typeof(StudentModel));
System.IO.StreamWriter writer = new System.IO.StreamWriter(testPath + "\\Test.xml");
serializer.Serialize(writer, studentModel);
writer.Close();
My Current output is
<?xml version="1.0" encoding="utf-8"?>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Max</name>
<number>1</number>
</StudentModel>
Required output is
<?xml version="1.0" encoding="utf-8"?>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Max</name>
<number>1</number>
</StudentModel>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Amy</name>
<number>2</number>
</StudentModel>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Jack</name>
<number>3</number>
</StudentModel>
It seems to me, that what you want to do is serialize a list (or array) of StudentModel to an xml. Currently you are only serializing one instance of StudentModel and overwrite the resulting xml each iteration of the loop, leaving you with the last item. What you can do, is to create a class with a List() of StudentModel as Property and serialize that class instance, not needing a loop anymore.
The List property in your new class would then look something like this:
[XmlArray("StudentModels"), XmlArrayItem(typeof(StudentModel), ElementName = "StudentModel")]
public List<StudentModel> StudentModelList{ get; set; }
I am working with a very large data set so need to write records to an xml file one at a time.
I have tried this code:
using (FileStream retryFile = System.IO.File.Create(filePath))
{
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var ser = new XmlSerializer(typeof(Record));
foreach(var item in veryLargeEnumerable)
{
ser.Serialize(retryFile, item, emptyNamespaces);
}
}
This writes the record but between every record it adds:
<?xml version="1.0"?>
When I try to read the file I get invalid format error.
How can I serialize objects one at a time to XML?
The code shown in your question generates an invalid xml hierarchy;
it doesn't contain a single root element, as each <Record> gets written at the root level, eg.:
<?xml version="1.0"?>
<Record>
<Name>foo</Name>
</Record><?xml version="1.0"?>
<Record>
<Name>bar</Name>
</Record><?xml version="1.0"?>
<Record>
<Name>baz</Name>
</Record>
You'll have to construct a single root element first.
Use an XmlWriter to do so, and then use that same XmlWriter as target to serialize the records into.
using (FileStream retryFile = System.IO.File.Create(filePath))
using (var xmlWriter = XmlWriter.Create(retryFile))
{
xmlWriter.WriteStartElement("Records");
var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var ser = new XmlSerializer(typeof(Record));
/* Your loop goes here. */
ser.Serialize(xmlWriter, new Record { Name = "foo" }, emptyNamespaces);
ser.Serialize(xmlWriter, new Record { Name = "bar" }, emptyNamespaces);
ser.Serialize(xmlWriter, new Record { Name = "baz" }, emptyNamespaces);
xmlWriter.WriteEndElement();
}
public class Record
{
public string Name {get; set; }
}
The xml wil then look like below, having a single root element <Records> containing the <Record> child elements.
<?xml version="1.0" encoding="utf-8"?>
<Records>
<Record><Name>foo</Name></Record>
<Record><Name>bar</Name></Record>
<Record><Name>baz</Name></Record>
</Records>
I have a XML file that contains this:
<?xml version="1.0" encoding="utf-8" ?>
<TokenToCardMapping>
<pair key ="2313123124122512" value="3412412512512512"/>
<pair key ="3414125121259723" value="3749327923749723"/>
</TokenToCardMapping>
I am looking for way to add a new pair element to the TokenToCardMapping descendants with XDocument or XElement.
I have the key and value as strings and I just want to add a new pair.
if my new key and value are: 111111111111 , 222222222222 I want to update the xml to look like this:
<?xml version="1.0" encoding="utf-8" ?>
<TokenToCardMapping>
<pair key ="2313123124122512" value="3412412512512512"/>
<pair key ="3414125121259723" value="3749327923749723"/>
<pair key ="111111111111" value="222222222222"/>
</TokenToCardMapping>
It is easy with LINQ to XML
// create new element
var newElement = new XElement("pair",
new XAttribute("key","111111111111"
new XAttribute("value","222222222222"));
// load the XML Document
var xDoc = XDocument.Load("path");
// Add new element to the root element
xDoc.Root.Add(newElement);
//And save the XML file
xDoc.Save("path")
Note: You need to add a reference to System.Xml.Linq.dll from your project
And I would recommend you read the LINQ to XML tutorial for more details.
Friends,
My school project is having an xml data file:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>Somewhere</add>
<mobile>0000</mobile>
.
.
.
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
My Windowsform "EditPatients_Load" is able to fetch all info of patient Jhon, and now let's assume that the Admin needs to change some information in the form & resubmit.
Then how to write back all values to Jhon's account in the same xml
file????
I'm not able to makeup the logical code, even if I check the node if (patients.paptient.name = "nameComboBox.text").... how to make sure that I'm writing other values on proper place?
Rgrdz,
Try this:
//string xml =
//#"<patients><patient><regNo>2012/Mar/003</regNo><name>Jhon</name><add>Somewhere
//</add><mobile>0000</mobile><stay>2</stay><costofroom>100</costofroom><total>200</total>
//</patient></patients>";
XDocument xmlDoc = XDocument.Load(#"c:\abc.xml");
var items = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item);
if (items.Count() > 0)
{
var item = items.First();
item.SetElementValue("add", "New New Address");
xmlDoc.Save(#"c:\abc.xml", SaveOptions.None);
}
You can get single element using
var item = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item).FirstOrDefault();
then update it using SetElementValue() method.
//Updated Xml
<?xml version="1.0" encoding="utf-8"?>
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>New Address</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
Reference:
Update XML with C# using Linq
I would take the xml serialization/deserialization route to solve this:
http://support.microsoft.com/kb/815813
How to Deserialize XML document
That way you can work with objects and not have to parse xml files manually.
If you're using .NET 3.5 onward you can use the XDocument class like the following. I'm assuming your content is in a .xml file.
XDocument xdoc = XDocument.Load(#"C:\Tmp\test.xml");
//this would ensure you get the right node and set its text content/value
xdoc.Element("patients")
.Element("patient").Element("add").Value = "some new address?";
xdoc.Save(#"C:\Tmp\test.xml");
The file test.xml would change to:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>some new address?</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
I've got a pretty nasty problem with xml serialization - I need to add some special information to the resulting xml-file:
Currently, it looks like
<?xml version="1.0" encoding="iso-8859-1"?>
<ORDER_LIST>
<ORDER version="1.0" xmlns="http://www.opentrans.org/XMLSchema/1.0">... shortened ...</ORDER>
<ORDER version="1.0" xmlns="http://www.opentrans.org/XMLSchema/1.0">... shortened ...</ORDER>
<ORDER version="1.0" xmlns="http://www.opentrans.org/XMLSchema/1.0">... shortened ...</ORDER>
</ORDER_LIST>
but it should look like
<?xml version="1.0" encoding="iso-8859-1"?>
<ORDER_LIST>
<ORDER xmlns="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" type="standard">... shortened ...</ORDER>
<ORDER xmlns="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" type="standard">... shortened ...</ORDER>
<ORDER xmlns="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" type="standard">... shortened ...</ORDER>
</ORDER_LIST>
The additional namespace (xmlns:xsi) and the xsi:schemaLocation / type attributes should be added to the result.
Actually my code is:
[XmlTypeAttribute(Namespace="http://www.opentrans.org/XMLSchema/1.0")]
public class OrderContainer
{
[XmlElementAttribute("ORDER")]
public List<ORDER> orderList;
}
---- snip ----
string xmlString;
XmlWriterSettings settings = new XmlWriterSettings()
{
Encoding = Encoding.GetEncoding("ISO-8859-1"),
Indent = true,
IndentChars = "\t",
NewLineChars = Environment.NewLine,
ConformanceLevel = ConformanceLevel.Document,
};
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
var testOrder = new ORDER();
var orderContainer = new OrderContainer();
orderContainer.orderList = new List<ORDER>();
orderContainer.orderList.Add(testOrder);
XmlSerializer serializer = new XmlSerializer(typeof(List<ORDER>), new XmlRootAttribute("ORDER_LIST"));
using (MemoryStream ms = new MemoryStream())
{
using (XmlWriter writer = XmlTextWriter.Create(ms, settings))
serializer.Serialize(writer, orderList, ns);
xmlString = Encoding.ASCII.GetString(ms.ToArray());
}
Console.WriteLine(xmlString);
It works really fine - except for the namespaces and attributes on the ORDER elements.
Background-information: The ORDER class is created from the openTrans-definition (opentrans_order_1_0_all_in_one.xsd).
It's been translated into C# classes using Xsd2Code (Xsd2Code).
Because of the automatic generation, adorning the class with attributes is not easily possible - I guess?
Thanks for any hint!
(Edited some information)
I know its a little late to reply to this question, but nonetheless I am answering in case someone in need stumbles upon this question.
I order to add namespaces you need to use this class: System.Xml.Serialization. XmlSerializerNamespaces, which I see in the problem code that it has been defined.
Following is the syntax that I have used to add namespaces while dealing with the xCBL Xml Schema:
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlns; //Defined as the Field of the class you want to serialize
//Defined in the Constructor
xmlns = new XmlSerializerNamespaces();
xmlns.Add("core", "rrn:org.xcbl:schemas/xcbl/v4_0/core/core.xsd");
This will add the namespace in the generated Xml like this:
xmlns:core="rrn:org.xcbl:schemas/xcbl/v4_0/core/core.xsd"
What it should look like is:
<?xml version="1.0" encoding="iso-8859-1"?>
<ORDER_LIST xmlns:trans="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" >
<trans:ORDER type="standard" >... shortened ...</ORDER>
<trans:ORDER type="standard" >... shortened ...</ORDER>
<trans:ORDER type="standard" >... shortened ...</ORDER>
</ORDER_LIST>
I'm not familar with xsd2code, but if you were hand coding, you need to put attributes.
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.opentrans.org/XMLSchema/1.0")]
[System.Xml.Serialization.XmlElementAttribute("Order")]
public class Order() {
String Type
}
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.opentrans.org/XMLSchema/1.0")]
[System.Xml.Serialization.XmlRootAttribute("OrderList", Namespace="http://www.opentrans.org/XMLSchema/1.0", IsNullable=false)]
public class OrderList() {
List<Orders>
}
try this. it's a libary to create or read opentrans documents!
http://opentrans.wordpress.com/