Convert plain string to XML format - c#

If I receive a string that is only a list of numbers (e.g. 1,2,3,5), is it possible to convert it to XML format, like this?
<foo>
<id>1</id>
<id>2</id>
<id>3</id>
</foo>
So far I had planned to use something along the lines of this
string s = "example";
XmlDocument xm = new XmlDocument();
xm.LoadXml(string.Format("<foo>{0}</foo>", s));
But I'm unsure as to how I should split the string so that I only get the numbers without using the obvious Split(), which is something my manager doesn't want me to do (otherwise I'd just skip the whole XML format).
Basically, is there a way for me to 'easily' serialize that string into XML format?

Use LINQtoXML
string items="1,4,6,3";
XElement elm = new XElement("foo");
foreach(var item in items.Split(','))
{
elm.Add(new XElement("id",item));
}
Now ele will have the XML you are looking for

You can use the XDocument.Parse(string) method
You can build up the xml string and then pass it to the method
http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.parse.aspx

Related

XML: Retrieve a particular value from xml

From the following XML, I want to find a value based on the Employer.
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Details>
<Employer>Taxes</Employer>
<Adr>
<Strt>Street</Strt>
<Twn>Town</Twn>
</Adr>
</Details>
<DetailsAcct>
<Recd>
<Payroll>
<Id>9</Id>
</Payroll>
</Recd>
<br>
<xy>A</xy>
</br>
</DetailsAcct>
</Document>
the C# code I applied is
detail = root.SelectSingleNode($"//w:Document//w:Employer[contains(text(), 'Taxes']/ancestor::Employer",nsmgr);
But it gives me an invalid token error.
What am I missing?
The error was due to [contains(...], notice closing parentheses is missing. And since you want to return Employer element, no need for ancestor::Employer here :
//w:Document//w:Employer[contains(., 'Taxes')]
If the XML posted resembles structure of the actual XML (except the namespaces), better to use more specific XPath i.e avoid using costly // :
/w:Document/w:Details/w:Employer[contains(., 'Taxes')]
An alternative is to use LINQ to XML.
If the XML is in a string:
string xml = "<xml goes here>";
XDocument document = XDocument.Parse(xml);
XElement element = document.Descendants("Employer").First();
string value = element.Value;
If the XML is in a .xml file:
XDocument document = XDocument.Load("xmlfile.xml");
XElement element = document.Descendants("Employer").First();
string value = element.Value;
You can also find an employer element with a specific value, if that's what you need:
XElement element = document.Descendants("Employer").First(e => e.Value == "Taxes");
Note: this will throw an exception if no element is found with the specified value. If that is not acceptable, then you can replace .First(...) with .FirstOrDefault(...) which will simply return null if no element is found.

Insert XML into an XML element

I have a string containing some XML:
<some>
<xml></xml>
<tags/>
<TheData/>
<more>asdf</more>
<of/>
<them></them>
</some>
Instead of <TheData/> we could have <TheData></TheData> or other equivalent forms.
Questions:
1: How can I make sure that the XML does indeed contain an empty TheData element?
2: How can I insert another XML string, HTML encoded into TheData? Example of the other XML:
<mydata>
<name>John</name>
<address>New York City</address>
</mydata>
End result:
<some>
<xml></xml>
<tags/>
<TheData>
<mydata>
<name>John</name>
<address>New York City</address>
</mydata>
</TheData>
<more>asdf</more>
<of/>
<them></them>
</some>
Are there quick ways to do this with e.g. LINQ to XML?
First of all, you have to load your XML into memory as an XDocument instance:
var doc = XDocument.Load(yourFilePath);
Then, you can answer your questions:
1: How can I make sure that the XML does indeed contain an empty TheData element?
var theData = doc.Root.Element("TheData");
if(theData != null && string.IsNullOrEmpty((string)theData))
{
// document contains TheData element which is empty
}
2: How can I insert another XML string, HTML encoded into TheData?
theData.Value = #"<mydata>
<name>John</name>
<address>New York City</address>
</mydata>";
You don't have to bother about XML encoding here. XElement class will take care of that.

Reading XML using C# is this the proper approach?

I have a project where i read XML that was exported from another system. The XML looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?><xmlimexport>
<companydata/>
<articles/>
<customers/>
<suppliers/>
<orders>
<order>
<atOrder>
<OOI_HEAD_DOCUMENT_NUMBER>12345</OOI_HEAD_DOCUMENT_NUMBER>
**... more rows ...**
</atOrder>
<rows>
<row><OOI_ROW_ARTICLE_NUMBER>12345</OOI_ROW_ARTICLE_NUMBER><OOI_ROW_ARTICLE_TEXT>SuperDuperArticleName</OOI_ROW_TEXT>**... more data...**</row>
</rows>
</order>
</orders>
<bests/>
<invoices/>
<supplierinvoices/>
<pricelists/>
<parcels/>
</xmlimexport>
So what i do is load the path to the XML file then:
XmlDocument doc = new XmlDocument();
// Load xml file
doc.Load(xmlFile);
// Read order data
XmlNodeList orderList = doc.GetElementsByTagName("order");
foreach (XmlElement order in orderList)
{
try
{
// Read atOrder data (single node)
XmlNode atOrder = order.SelectSingleNode("atOrder");
// Read article data (one or many nodes)
XmlNodeList articles = order.GetElementsByTagName("row");
// Create a order
Order customerOrder = new Order();
Then read data with:
customerOrder.CUS_ID = Convert.ToInt32(atOrder.SelectSingleNode("OOI_HEAD_DOCUMENT_NUMBER").InnerText);
But since it can be both Strings, Booleans, Datetime, Date and INT in those fields i find myself having to use Convert. very much, is this the proper way to do this or should i use a different approach?
you can also generate an XSD and based on an XSD a class to deserialize the XML (short tutorial here)
you can read the XML directly into a DataSet (.ReadXML)
Have a look at LinqToXml I think that might help:
http://msdn.microsoft.com/en-us/library/bb387098.aspx

XmlSerializer Deserializing Array/List of Multiple Objects at Root

I'm trying to deserialize the following XML output:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Foo>
<Val>Data1</Val>
</Foo>
<Foo>
<Val>Data2</Val>
</Foo>
(This is output from a hardware device, and cannot be changed)
I have an XML type defined as:
[XmlType(AnonymousType=true, Namespace="")]
public class Foo
{
public string Val { get; set; }
}
I've tried to deserialize this array by creating a serializer like:
var s = new XmlSerializer(typeof(Foo[]));
//or
var s = new XmlSerializer(typeof(List<Foo>);
But every call to s.Deserialize() causes an InvalidOperaitonException:
System.InvalidOperationException: <Foo xmlns=''> was not expected.
Note
var s = new XmlSerializer(typeof(Foo));
// Only deseralizes the first Foo (Data1).
Thanks for your help.
I think the issue is with your provided xml.
Test app says
List<Foo> list = new List<Foo> {new Foo {Val = "Data1"}, new Foo {Val = "Data2"}};
var s = new XmlSerializer(typeof(List<Foo>));
StringBuilder sb = new StringBuilder();
XmlWriter wr = XmlWriter.Create(sb);
s.Serialize(wr, list);
string ss = sb.ToString();
var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(ss);
List<Foo> returnList = (List<Foo>)s2.Deserialize(sr);
And the XML should be
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfFoo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Foo>
<Val>Data1</Val>
</Foo>
<Foo>
<Val>Data2</Val>
</Foo>
</ArrayOfFoo>
If you can remove the inital line
<?xml version="1.0" encoding="ISO-8859-1"?>
And minipulate the string into
string s = "<ArrayOfFoo><Foo> <Val>Data1</Val></Foo><Foo> <Val>Data2</Val></Foo></ArrayOfFoo>";
var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(s);
List<Foo> list = (List<Foo>)s2.Deserialize(sr);
That could work.
That isn't valid Xml. There needs to be a core root element for it to work properly.
this is not a valid xml so you can not deserialize it like a valid xml. You need some kind of hack to make this work. i'd suggest to insert at beginning of the xml and inserting at the end of xml. then you can deserialize it, since you cant make this change at xml side, do it in your code.
String ss;
// lets assume this holds your xml data in string.
ss.append("</ArrayOfFoo>");
ss.replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "<?xml version=\"1.0\" encoding=\"utf-16\"?> <ArrayOfFoo>")
var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(ss);
List<Foo> returnList = (List<Foo>)s2.Deserialize(sr);
now this shall return you the correct list.
As the other posters say, this XML that the hardware device produces is not compatible to the way .NET serializes/deserializes object. Valid XML, and .NET requires valid XML, has a root element.
I suggest:
either you modify your obtained XML to match the way astander presents in his xml code snippet.
or you write a simple xml parser for your file that deserializes the file like you need
br, Marcel
Technically, what you have there is not a well-formed XML document (which has exactly one root element), but rather an well-formed external parsed entity (which can have any number of elements not contained in other elements, as well as text not contained in any elements). Therefore, it should parse if your XML parser has an entry point for parsing EPEs rather than documents. You could also create a stub document which includes by reference your EPE and parse that document.
Xstream for .Net could be a useful API

Get html tags embedded in xml using linq

I have a basic xml file that looks like this.
<root>
<item>
<title><p>some title</p></title>
</item>
...
</root>
What I want, is to get the whole title string including the html tag of the xml using linq and displaying it in a repeater .
I can get the title with no problem, but the <p> tag is being stripped out.
If I use
title = item.Element("title").ToString(), it works somehow but I get all the xml tag as well - meaning the title is not displayed in html.
I already tried with encoding the "<" with "<" but to do this makes the xml hard to read.
What would be a possible solution besides using CDATA and encoding?
Cheers
Terry
Create a reader from the title element and read InnerXml:
static void Main(string[] args)
{
string xml = "<root><item><title><p>some title</p></title></item></root>";
XDocument xdoc = XDocument.Parse(xml);
XElement te = xdoc.Descendants("title").First();
using (XmlReader reader = te.CreateReader())
{
if (reader.Read())
title = reader.ReadInnerXml();
}
}
See Best way to get InnerXml of an XElement? for some ideas on how to get the "InnerXml" of an XElement.
XElement x = XElement.Parse(your xml);
var y= x.Descendants("title").Descendants();
Then iterate y for a list of the contents of the title elements.
BTW, LINQPad (http://www.linqpad.net) is a handy free tool for trying out LINQ-XML.

Categories