I have been trying to make an export/import program but when I try to import the XML-information to the textbox it doesn't work.
C# snippet from program:
XmlDocument doc = new XmlDocument();
doc.Load(open.FileName);
foreach (XmlNode x in doc.DocumentElement)
textBox6.Text = x["Contact"].Value;
and the XML-file is as follows:
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
<Table1>
<Contact>example</Contact>
</Table1>
</NewDataSet>
Original image:
http://i.stack.imgur.com/0ks2F.png
try use InnerText instead of value
textBox6.Text = x["Contact"].InnerText;
A breakpoint on the line
textBox6.Text = x["Contact"].Value;
should be revealing...
That's just based on visual inspection - people who supply XML as png files don't get it examined by me lol...
You can use XmlSerializer to achieve same operation.
Checkout following code.
using System.Xml.Serialization;
using System.IO;
namespace DemoApplication
{
class Program
{
static void Main(string[] args)
{
NewDataSet objNewDataSet = new NewDataSet();
Table objTable = new Table();
objTable.Conact = "Hello";
objNewDataSet.Table1 = objTable;
StreamWriter objStream = new StreamWriter("C:\\Users\\Nirav Kamani\\Desktop\\abc.xml");
XmlSerializer objXmlSerializer = new XmlSerializer(typeof(NewDataSet));
objXmlSerializer.Serialize(objStream, objNewDataSet);
}
}
}
Model Classes.
using System.Xml.Serialization;
namespace DemoApplication
{
public class NewDataSet
{
[XmlElement]
public Table Table1 { get; set; }
}
}
namespace DemoApplication
{
public class Table
{
public string Conact { get; set; }
}
}
You can serialize and deserialize easily.
For more information check out following links.
I am just giving you a better approach to achieve same operation in terms of objects.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx
Related
I do have a problem with serialization of a namespaces. As my code show below my logic fills the structure of my dictionary, serializes it and puts into a string variable. I use this variable to load into XMLDocument and after that I do add the namespaces. But since they are added after the serialization process the namespaces are set in UTF8? Should I add namespaces before serialization? If yes, how can I do it properly?
///Dictionary
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace TestXML
{
[Serializable]
[XmlRoot(ElementName = "Root")]
public class XMLSchema: Serialization
{
[XmlElement(ElementName = "Element1")]
public XMLElement1 Element1 { get; set; }
[XmlElement(ElementName = "Element2")]
public XMLElement2 Element2 { get; set; }
}
}
///Serialization class
public class Utf8StringWriter : StringWriter
{
// Use UTF8 encoding
public override Encoding Encoding
{
get { return new UTF8Encoding(false); }
}
}
public string Serialize()
{
var xmlserializer = new XmlSerializer(this.GetType());
var Utf8StringWriter = new Utf8StringWriter();
var xns = new XmlSerializerNamespaces();
xns.Add(string.Empty, string.Empty);
using (var writer = XmlWriter.Create(Utf8StringWriter))
{
xmlserializer.Serialize(writer, this, xns);
return Utf8StringWriter.ToString();
}
}
///create xml
str xml;
[...] my logic to add data into elements
XmlDocument doc = new XmlDocument();
xml = XMLSchema.Serialize();
doc.LoadXml(xml);
XmlElement root = doc.getNamedElement("Root");
root.SetAttribute("xmlns:etd", "http://google.com");
root.SetAttribute("xmlns:xsi", "http://google.com");
root.SetAttribute("xmlns", "http://google.com");
doc.AppendChild(root);
doc.Save(path);
Edit. Adding provided sample.
<?xml version="1.0" encoding="UTF-8"?> <XMLSample xmlns="http://crd.gov.pl/wzor/" xmlns:xsi="http://www.w3.org/2001/" xmlns:etd="http://crd.gov.pl/xml/schematy/">
So to give you an example (based on your sample):
[XmlRoot("XMLSample", Namespace = "http://crd.gov.pl/wzor/")]
public class XmlSample
{
[XmlElement]
public string Element1 { get; set; }
[XmlElement(Namespace = "http://crd.gov.pl/xml/schematy/")]
public string Element2 { get; set; }
}
Here, the root has the namespace http://crd.gov.pl/wzor/. Element1 inherits that namespace (as none is specified). Element2 has the namespace http://crd.gov.pl/xml/schematy/.
When this is serialised, the serialiser will use the root namespace as the default, so there's no need to explicitly set this. You can set the others to use the prefixes as defined in your sample:
var xsn = new XmlSerializerNamespaces();
xsn.Add("xsi", "http://www.w3.org/2001/");
xsn.Add("etd", "http://crd.gov.pl/xml/schematy/");
You can see this fiddle for a demo, the output is:
<?xml version="1.0" encoding="utf-8"?>
<XMLSample xmlns:xsi="http://www.w3.org/2001/" xmlns:etd="http://crd.gov.pl/xml/schematy/" xmlns="http://crd.gov.pl/wzor/">
<Element1>foo</Element1>
<etd:Element2>bar</etd:Element2>
</XMLSample>
Note that Element2 uses the prefix configured for its namespace.
I am trying to change values inside XML file. This is my XML "person.xml" file:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Table>
<Person>
<Number>1</Number>
<Name>Mariano</Name>
<Last Name>Italiano</Last Name>
<Age>36</Age>
</Person>
<Person>
<Number>2</Number>
<Name>John</Name>
<Last Name>Smith</Last Name>
<Age>32</Age>
</Person>
<Person>
<Number>3</Number>
<Name>Bob</Name>
<Last Name>Leckie</Last Name>
<Age>50</Age>
</Person>
<Person>
<Number>4</Number>
<Name>Patrick</Name>
<Last Name>Collins</Last Name>
<Age>63</Age>
</Person>
</Table>
And i want my program to do some things:
Find a name written in textBox2->Text. Then if the name exists i want to change it to name written in textBox3->Text.
Remove (if found) whole Person if CheckBoxDelete is set to true
I know how to create such a XML file (found an example somewhere) but i can't find a solution how to find and remove if neccessary.
I am using Visual Studio 2015 if it matters.
Thank You.
You can use XDocument to replace the value and delete the person according to the Name.
Code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string filename = "D:\\test.xml";
private void BtnRePlace_Click(object sender, EventArgs e)
{
XDocument doc = XDocument.Load(filename);
doc.Descendants("Person").Descendants("Name").Where(i => i.Value == txtReplaceFirstName.Text).FirstOrDefault().SetValue(txtReplaceLastName.Text);
doc.Save(filename);
}
private void btndelete_Click(object sender, EventArgs e)
{
XDocument doc = XDocument.Load(filename);
doc.Descendants("Person").Where(i => i.Element("Name").Value == txtReplaceFirstName.Text&& i.Element("LastName").Value == txtReplaceLastName.Text).FirstOrDefault().Remove();
doc.Save(filename);
}
}
Besides, your xml file have an error, the Last Name should be LastName without space.
You could map (i.e. deserialize) the data to POCO objects, manipulate the data and serialize again. Might be a bit overkill though. As others stated, using XDocument might be good enough.
Here is a minimal example:
public class Person
{
[XmlElement]
public int Number { get; set; }
[XmlElement]
public string Name { get; set; }
[XmlElement]
public string LastName { get; set; }
[XmlElement]
public int Age { get; set; }
public override string ToString() => $"{Name} {LastName} is {Age}";
}
[XmlRoot("Table")]
public class RootObject
{
[XmlElement("Person")]
public List<Person> Persons;
}
class Program
{
static void Main(string[] args)
{
var xmlSer = new XmlSerializer(typeof(RootObject));
using var fs = new FileStream("input.xml", FileMode.Open);
var doc = (RootObject)xmlSer.Deserialize(fs);
foreach (var p in doc.Persons)
{
System.Console.WriteLine(p);
}
// do whatever with the RootObject instance
}
}
XML is the object, so consider re-using existing objects before creating more POCOs.
Here's code that shows how to find, delete, and update elements in XML. Take some time to learn XPath, it's very powerful, flexible, and available across nearly every platform.
using System;
using System.Threading.Tasks;
using System.Xml;
namespace testconsole
{
class Program
{
public static string strFileName = "c:\\temp\\test.xml";
static void Main(string[] args) {
XmlDocument xml = new XmlDocument();
xml.Load(strFileName);
string strMatchName = "Mariano";
string strXPath = "/Table/Person[Name='" + strMatchName + "']";
XmlElement ndPerson = (XmlElement)xml.SelectSingleNode(strXPath);
if (ndPerson != null) {
// Delete if the person is found
ndPerson.ParentNode.RemoveChild(ndPerson);
}
string strNewName = "Bob";
strXPath = "/Table/Person/Name[.='" + strNewName + "']";
XmlElement ndName = (XmlElement)xml.SelectSingleNode(strXPath);
if (ndName != null) {
ndName.InnerText = "Robert"; // new name
}
xml.Save(strFileName);
}
}
}
How to create a C# class which must be used to deserialize the XML as given below
<?xml version="1.0" encoding="utf-8"?>
<XML>
<StatusCode>-2</StatusCode>
<Warnings />
<Errors>
<Error> Debtor #2 Invalid Postal Code</Error>
<Error>Invalid lien term</Error>
</Errors>
</XML>
Try following :
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);
XmlSerializer serializer = new XmlSerializer(typeof(XML));
XML xml = (XML)serializer.Deserialize(reader);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(OUTPUT_FILENAME, settings);
serializer.Serialize(writer, xml);
}
}
public class XML
{
public int StatusCode { get; set; }
public string Warnings { get; set; }
[XmlArray("Errors")]
[XmlArrayItem("Error")]
public List<string> errors { get; set; }
}
}
To create classes based on XML, copy the xml to the clipboard, then in Visual Studio 2017, choose the menu option: Edit/Paste Special/Paste XML as classes.
Your Class should look like:
public class ErrorClass
{
struct Error
{
public String message;
}
struct Warning
{
public String message;
}
int StatusCode;
List<Error> Errors;
List<Warning> Warnings;
}
Error and Warning struct could contain more items that are not used in the example you posted.
I have XML within a C# program that looks something like this:
<el1 xmlns="http://URI1">
<el2 xmlns:namespace2="http://URI2"></el2>
<el3>
<el4 xmlns:namespace3="http://URI3"></el4>
</el3>
</el1>
For cleanliness, I would like to move all the namespace declarations to the root element. I cannot change the export that produces this XML, so a solution needs to work on the sample as shown above. What is a good way to accomplish this?
This example is stripped down for brevity, but assume that there are further child elements that actually use these prefixes. These are irrelevant for this question as all the namespace prefix declarations are unique and my goal is only to move them higher in the tree.
I've reviewed the MSDN documentation for XML but there doesn't seem to be a simple way to manipulate namespaces like this. One of the solutions I've tried is interacting with the XML as an XElement and collecting the namespaces based on XAttribute.IsNamespaceDeclaration, replacing each element with its local name and finally creating a new root element with the collected list of namespace XAttributes. That line of experimentation caused a bunch of errors about redefining prefixes, though, and I'm not sure if I'm moving in the right direction or not.
You need to add a prefix
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
El1 el1 = new El1()
{
el2 = new El2()
{
el3 = new El3() {
el4 = new El4() {
}
}
}
};
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("u4", "http://URI4");
ns.Add("u3", "http://URI3");
ns.Add("u2", "http://URI2");
ns.Add("", "http://URI1");
XmlSerializer serializer = new XmlSerializer(typeof(El1));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, el1, ns);
writer.Flush();
writer.Close();
writer.Dispose();
}
}
[XmlRoot("el1", Namespace = "http://URI1")]
public class El1
{
[XmlElement("el2", Namespace = "http://URI2")]
public El2 el2 { get; set; }
}
[XmlRoot("el2")]
public class El2
{
[XmlElement("el3", Namespace = "http://URI3")]
public El3 el3 { get; set; }
}
[XmlRoot("el3", Namespace = "http://URI3")]
public class El3
{
[XmlElement("el4", Namespace = "http://URI4")]
public El4 el4 { get; set; }
}
[XmlRoot("el4", Namespace = "http://URI1")]
public class El4
{
}
}
You can locate all the xmls attributes using the namespace xpath axis. Add those attributes to the root element. Finally write out the xml using NamespaceHandling.OmitDuplicates, which will leave the namespace declarations on the root and remove them from all the other elements.
var xml = new XmlDocument();
xml.Load("XMLFile1.xml");
// Find all xmlns: attributes
var attributes = xml.DocumentElement.SelectNodes("//namespace::*");
// Add xmlns: attributes to the root
foreach (XmlAttribute attribute in attributes)
xml.DocumentElement.SetAttribute(attribute.Name, attribute.Value);
// Write out results, ignoring duplicate xmlns: attributes
var settings = new XmlWriterSettings();
settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
settings.Indent = true;
using (var writer = XmlWriter.Create("XMLFile2.xml", settings))
{
xml.Save(writer);
}
[XmlRoot("Class1")]
class Class1
{
[(XmlElement("Product")]
public string Product{get;set;}
[(XmlElement("Price")]
public string Price{get;set;}
}
This is my class. In this the price contains the '£' symbol. after serializing it to XML I get the '?' instead of '£'.
what I need to do to get the '£' in XML? OR How can I pass the data in price as CDATA?
Your problem must be to do with how the XML is written to the file.
I've written a program that uses the information that you've given me so far, and it when I print the XML string out, it is correct.
I conclude that the error is happening either when the data is written to the XML file, or when it is read back in from the XML file.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
new Program().Run();
}
void Run()
{
Class1 test = new Class1();
test.Product = "Product";
test.Price = "£100";
Test(test);
}
void Test<T>(T obj)
{
XmlSerializerNamespaces Xsn = new XmlSerializerNamespaces();
Xsn.Add("", "");
XmlSerializer submit = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
XmlWriter writer = XmlWriter.Create(stringWriter);
submit.Serialize(writer, obj, Xsn);
var xml = stringWriter.ToString(); // Your xml This is the serialization code. In this Obj is the object to serialize
Console.WriteLine(xml); // £ sign is fine in this output.
}
}
[XmlRoot("Class1")]
public class Class1
{
[XmlElement("Product")]
public string Product
{
get;
set;
}
[XmlElement("Price")]
public string Price
{
get;
set;
}
}
}