Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2250
  • Last Modified:

Reading XML from a String variable in C#

A  String Variable 'str' is having following value
<?xml version="1.0" encoding="utf-8"?>
<Transaction>
  <firstName>FirstName</firstName>
  <lastName>LastName</lastName>
  <street>Street</street>
  <zip>54321</zip>
  <city>City</city>
  <country>LV</country>
  <email>kumar@gmail.com</email>
  <ip>123.124.125.126</ip>
  <value>1000</value>
  <currency>USD</currency>
  <productName>Product Name</productName>
  <productUrl>www.test.com</productUrl>
  <orderNumber>9865391</orderNumber>
</Transaction>

How can I read it so that i get firstName, lastName etc.
0
Dinesh Kumar
Asked:
Dinesh Kumar
  • 13
  • 8
  • 2
  • +1
4 Solutions
 
HugoHiaslCommented:
You can fill it to an XML DOM by using

XmlDocument doc = new XmlDocument();
doc.Parse(<yourstring>);
   
XmlElement root = doc.DocumentElement;

After this you can access it with standard Xpath:

root["firstName"].InnerText;
root["lastName"].InnerText;
0
 
Dinesh KumarAuthor Commented:
doc.Parse in c# does not exist.
0
 
HugoHiaslCommented:
Hmm.. Sorry.. This was Linq

Use

doc.LoadXml(<yourstring>)

instead.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Dinesh KumarAuthor Commented:
HugoHias:, can you replace Parse with LoadXml so that I can accept your solution as a whole at one place.
0
 
Dinesh KumarAuthor Commented:
Problem coming in doc.LoadXml(<yourstring>)
System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
   at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
   at System.Xml.XmlDocument.Load(XmlReader reader)
   at System.Xml.XmlDocument.LoadXml(String xml)
   at ImsWebService.Transaction.CREATE(HttpContext context) in some file.

0
 
jaya_banbahCommented:
Hi,

This exception is mostly because of some white spaces at the starting position.My guess is that when you are placing it in the string variable , there are some spaces in the starting position.
0
 
Dinesh KumarAuthor Commented:

I tried trim as follows..
byte[] PostData = context.Request.BinaryRead(context.Request.ContentLength);
                //Convert the bytes to string using Encoding class
                string str = Encoding.UTF8.GetString(PostData);
                WriteResponse(str);
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(str);
                XmlElement root = doc.DocumentElement;                
                WriteResponse(root["email"].InnerText.Trim());
but its not working.

whenever I try the following root["email"].InnerText it gives the error Data at the root level is invalid. Line 1, position 1
0
 
Dinesh KumarAuthor Commented:
Now the xml value is:
<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Transaction>\r\n  <firstName>DineshKumar</firstName>\r\n  <lastName>LastName</lastName>\r\n  <street>Street</street>\r\n  <zip>54321</zip>\r\n  <city>City</city>\r\n  <country>LV</country>\r\n  <email>kumar@gmail.com</email>\r\n  <ip>123.124.125.126</ip>\r\n  <value>10010</value>\r\n  <currency>USD</currency>\r\n  <productName>Product Name</productName>\r\n  <productUrl>www.test.com</productUrl>\r\n  <orderNumber>1231673</orderNumber>\r\n  <cardname>dineshKumar</cardname>\r\n  <cardnr>4314229999999913</cardnr>\r\n  <validMONTH>01</validMONTH>\r\n  <validYEAR>13</validYEAR>\r\n  <cvc2>123</cvc2>\r\n</Transaction>
0
 
Dinesh KumarAuthor Commented:
isn't there alternative of doc.LoadXml(<yourstring>)?
0
 
Dinesh KumarAuthor Commented:
Now The  XML is:
<?xml version='1.0' encoding='utf-8'?><Transaction><firstName>DineshKumar</firstName><lastName>LastName</lastName><street>Street</street><zip>54321</zip><city>City</city><country>LV</country><email>kumar@gmail.com</email><ip>123.124.125.126</ip><value>10010</value><currency>USD</currency><productName>Product Name</productName><productUrl>www.test.com</productUrl><orderNumber>123114173</orderNumber><cardname>dineshKumar</cardname><cardnr>4314229999999913</cardnr><validMONTH>01</validMONTH><validYEAR>13</validYEAR><cvc2>123</cvc2></Transaction>
0
 
jaya_banbahCommented:
I tried your string and it executed very well for me.
I am posting the code below:-
0
 
jaya_banbahCommented:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace XmlDom_try
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            XmlDocument xdoc = new XmlDocument();

            String str = @"<?xml version=" + '"' + "1.0" + '"' + " encoding=" + '"' + "utf-8" + '"' + "?>" +

   " <Transaction>  <firstName>FirstName</firstName>   <lastName>LastName</lastName>   <street>Street</street>"+
  "<zip>54321</zip>   <city>City</city>  <country>LV</country>  <email>kumar@gmail.com</email>"+
  "<ip>123.124.125.126</ip> <value>1000</value> <currency>USD</currency> <productName>Product Name</productName>"+
  "<productUrl>www.test.com</productUrl>   <orderNumber>9865391</orderNumber> </Transaction>";
            label2.Text = str;
         xdoc.LoadXml(str);

            XmlElement root = xdoc.DocumentElement;



            label1.Text= root["firstName"].InnerText;
label2.Text=root["lastName"].InnerText;
        }
    }
}

0
 
jaya_banbahCommented:
I am sorry couldn't post the code in "Code" section as provided in the site.My system is not working fine for now.
0
 
Dinesh KumarAuthor Commented:
  what is happening here
   XmlElement root = xdoc.DocumentElement;
    label1.Text= root["firstName"].InnerText;

0
 
Dinesh KumarAuthor Commented:
whenever I try to access the first approach in the processrequest handler:
I get the error like 'Data at the root level is invalid. Line 1, position 1'
so I thought that there might be some problem in generating the xml with code so I generated with the second approach. which worked well.

Do you see any drawback of it?
FIRST APPROACH(WHICH IS NOT WORKING)

 MemoryStream mStream = new MemoryStream();
        //XmlTextWriter xmlWriter = new XmlTextWriter(@"C:\Employee.xml", Encoding.UTF8);
        XmlTextWriter xmlWriter = new XmlTextWriter(mStream, Encoding.UTF8);
        xmlWriter.Formatting = Formatting.Indented;        
        xmlWriter.WriteStartDocument();
        xmlWriter.WriteStartElement("Transaction");
        
        xmlWriter.WriteStartElement("firstName");
        xmlWriter.WriteString(firstName);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("lastName");
        xmlWriter.WriteString(lastName);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("street");
        xmlWriter.WriteValue(street);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("zip");
        xmlWriter.WriteString(zip);
        xmlWriter.WriteEndElement();

        xmlWriter.WriteStartElement("city");
        xmlWriter.WriteString(city);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("country");
        xmlWriter.WriteString(country);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("email");
        xmlWriter.WriteString(email);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("ip");
        xmlWriter.WriteString(ip);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("value");
        xmlWriter.WriteString(value);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("currency");
        xmlWriter.WriteString(currency);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("productName");
        xmlWriter.WriteString(productName);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("productUrl");
        xmlWriter.WriteString(productUrl);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("orderNumber");
        xmlWriter.WriteString(orderNumber);
        xmlWriter.WriteEndElement();

        xmlWriter.WriteStartElement("cardname");
        xmlWriter.WriteString(cardname);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("cardnr");
        xmlWriter.WriteString(cardnr);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("validMONTH");
        xmlWriter.WriteString(validMONTH);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("validYEAR");
        xmlWriter.WriteString(validYEAR);
        xmlWriter.WriteEndElement();
        xmlWriter.WriteStartElement("cvc2");
        xmlWriter.WriteString(cvc2);
        xmlWriter.WriteEndElement();

        xmlWriter.WriteEndElement();
        xmlWriter.WriteEndDocument();
        xmlWriter.Flush();
        xmlWriter.Close();
        return mStream.ToArray();

SECOND APPROACH(WHICH IS WORKING):
   String postData = "<?xml version='1.0' encoding='utf-8'?>"+
        "<Transaction>"+
        "<firstName>"+firstName+"</firstName>"+
        "<lastName>" + lastName + "</lastName>" +
        "<street>" + street + "</street>" +
        "<zip>" + zip + "</zip>" +
        "<city>" + city + "</city>" +
        "<country>" + country + "</country>" +
        "<email>" + email + "</email>" +
        "<ip>" + ip + "</ip>" +
        "<value>" + value + "</value>" +
        "<currency>" + currency + "</currency>" +
        "<productName>" + productName + "</productName>" +
        "<productUrl>" + productUrl + "</productUrl>" +
        "<orderNumber>" + orderNumber + "</orderNumber>" +
        "<cardname>" + cardname + "</cardname>" +
        "<cardnr>" + cardnr + "</cardnr>" +
        "<validMONTH>" + validMONTH + "</validMONTH>" +
        "<validYEAR>" + validYEAR + "</validYEAR>" +
        "<cvc2>" + cvc2 + "</cvc2>" +
        "</Transaction>";
        byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(postData);
        return byteArray;

Open in new window

0
 
jaya_banbahCommented:
I tried you first approach and it did give me the error.When I check the value of the " postdata" string variable , it is prefixed with a wrong char,hence the error.
0
 
jaya_banbahCommented:
your First Approach works for me in the below mentioned code:-

 string str = Encoding.UTF8.GetString(mStream.ToArray());
           WriteResponse(str);  
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(str.Remove(0,1));

            XmlElement root = doc.DocumentElement;
            WriteResponse(root["email"].InnerText.Trim());
           
0
 
Dinesh KumarAuthor Commented:
jaya_banbah:
I tried you first approach and it did give me the error.When I check the value of the " postdata" string variable , it is prefixed with a wrong char,hence the error.

can you please send me the screenshot showing me the wrong char?
0
 
Dinesh KumarAuthor Commented:
if possible, what was the code error in first approach! very keen to know that
0
 
jaya_banbahCommented:
here's the screenshot for postdata string: Screenshot with the erroneous char in the begininning
0
 
jaya_banbahCommented:
the error was the same that you are getting for that code..
0
 
Dinesh KumarAuthor Commented:
1. converts to bytes with UTF8 encoding
2. bytes to string with UTF8 encoding  is creating problem of invalid char as seen in the attached image.

  I am still struggling why this invalid char is coming in the following code:
        MemoryStream mStream = new MemoryStream();
        //XmlTextWriter xmlWriter = new XmlTextWriter(@"C:\Employee.xml", Encoding.UTF8);
        XmlTextWriter xmlWriter = new XmlTextWriter(mStream, Encoding.UTF8);
        xmlWriter.Formatting = Formatting.Indented;        
        xmlWriter.WriteStartDocument();
        xmlWriter.WriteStartElement("Transaction");
        .....
        ....
invalid-char.JPG
0
 
AnilKumarSharmaCommented:
The UTF-8 encoding is clearly the way to go for using Unicode. In order to allow the automatic detection of the byte order, it has become customary on some platforms notably Win32) to start every Unicode file with the character U+FEFF (ZERO WIDTH NO-BREAK SPACE), also known as the Byte-Order Mark (BOM). Its byte-swapped equivalent U+FFFE is not a valid Unicode character, therefore it helps to unambiguously distinguish the Bigendian and Littleendian variants of UTF-16 and UTF-32.

A good encoding converter will also offer options for adding or removing the BOM:
•Unconditionally prefix the output text with U+FEFF.
•Prefix the output text with U+FEFF unless it is already there.
•Remove the first character if it is U+FEFF.
•The bytes 0xFE and 0xFF are never used for text in the UTF-8 encoding (as they are used for marking, see above)
0
 
AnilKumarSharmaCommented:
So the first charcter you see in your string is BOM.
Actually if using xmlparser,  XMLParser recognize BOM and automatically remove it. If you consider to remove BOM, then you probably have more problems with your current method than just trimming the byte order mark.
You can achieve the same as

private readonly string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
 if (str.StartsWith(_byteOrderMarkUtf8))
{
       str= str.Remove(0, _byteOrderMarkUtf8.Length);
}


0
 
Dinesh KumarAuthor Commented:
Thank you very much.
0

Featured Post

Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

  • 13
  • 8
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now