Converting XML to BsonArray in MongoDB using C# - c#

I have an XML file and I want to convert to BsonArray in MongoDB, later then I can make it a list of elements. Here is what I tried.
XmlDocument doc = new XmlDocument();
doc.Load("Books.xml");
string json_doc = JsonConvert.SerializeXmlNode(doc);
...
using (var jsonReader = new JsonReader(json_doc))
{
var context = BsonDeserializationContext.CreateRoot(jsonReader);
var document = XML_collection.DocumentSerializer.Deserialize(context);
}
Code converts XML to Json but not BsonArray. That means what I will get is only ONE document with hundreds of fields. But what I want is making them separate as a list.

You can use BsonDocument.Parse() to read your string and then you can access catalog.book path to cast into BsonArray:
var json_doc = JsonConvert.SerializeXmlNode(doc);
var bsonArray = BsonDocument.Parse(json_doc)["catalog"]["book"].AsBsonArray;

Related

Convert XML String API response to a key-value Object C#

I am receiving a XML strings from and API, and would like to convert these to C# objects key-value in order to handle these values also apply some asserts.
The messages are of the form string format:
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<ProjectName>Test Data</ProjectName>
<Unit>Unit 1</Unit>
<ReportLabel.Cost>394</ReportLabel.Cost>
</ReportData>
After i get the string API response i am trying to deserialize the XMl like this where responseAPI is the xml above:
XmlDocument doc = new XmlDocument();
using (var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(responseAPI), XmlDictionaryReaderQuotas.Max))
{
XElement xml = XElement.Load(reader);
doc.LoadXml(xml.ToString());
}
At this point i have and xml but i can not get a key-value object.
i am trying
var jsonText = JsonConvert.SerializeXmlNode(doc);
or
serializer = new XmlSerializer(typeof(Object));
using (TextReader reader = new StringReader(responseAPI))
{
var result = (Object)serializer.Deserialize(reader);
}
or
var response = JsonConvert.DeserializeObject<Dictionary<string, object>>(responseAPI);
I am new to with this kind of response in XML and am not sure the way to performing this. It is not as easy as JSON format.
You can use System.Xml.Linq for this task.
Here is one way to create a dictionary from the XML:
static void Main(string[] args)
{
// or use other overload of the Load() method if the XML is not comes from a file stream, uri etc...
var xmldoc = System.Xml.Linq.XDocument.Load("YOUR FILE PATH");
Dictionary<string, string> XMLKeyval = new Dictionary<string, string>();
foreach (var name in xmldoc.Descendants("ReportData").Elements()
.Select(x => new { Name = x.Name, Value = x.Value }).Distinct())
{
XMLKeyval.Add(name.Name.LocalName, name.Value);
}
// Output
foreach (KeyValuePair<string, string> itm in XMLKeyval)
{
Console.WriteLine(itm.Key + ": " + itm.Value);
}
Console.ReadLine();
}
You can not directly convert xml to a dict of key value pair, Instead we need to iterate through each node in xml and add it as a key value pair to a dict object.
please refer Converting an XML-document to a dictionary

Error while defining XPathSelectElement c#

I have a complex XML file where I want to retrieve different values from the different Set tag.At the end, i need to take the values to a CSV file.
Please see the xml file format
I am trying to retrieve the value of
<szItemID>3268750004533</szItemID> from the first set
<lMerchandiseStructureID>40</lMerchandiseStructureID> from the second set
<szDesc>PHG VIANDE SECHEE DE</szDesc> from the third set
<dPackingUnitPriceAmount>75</dPackingUnitPriceAmount> from the fourth tag
I have tried to retrieve the first element through the below code but getting an error
NullReferenceException was unhandled
Object reference not set to an instance of an object
Code
XmlDocument document = new XmlDocument();
document.Load(#"D:\\xml_1.xml");
string myXmlString = document.OuterXml.ToString();
XElement xml = XElement.Parse(myXmlString);
Console.WriteLine(string.Format("{0}",xml.XPathSelectElement("/UpdateDB/Transaction/Insert/Set/szItemID").Value));
Please help
StringBuilder dataToBeWritten = new StringBuilder();
var doc = XDocument.Load(#"D:\xml_2.xml");
foreach (var trans in doc.Descendants("Transaction"))
{
var val3 = (string)doc.Descendants("Set").Elements("szItemID").First();
var val4 = (string)doc.Descendants("Set").Elements("lMerchandiseStructureID").First();
var val5 = (string)doc.Descendants("Set").Elements("szName").First();
var val6 = (string)doc.Descendants("Set").Elements("lRetailStoreID").First();
var val7 = (string)doc.Descendants("Set").Elements("bIsContract").First();
dataToBeWritten.Append(val3);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val4);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val5);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val6);
dataToBeWritten.Append(",");
dataToBeWritten.Append(val7);
dataToBeWritten.Append(",");
dataToBeWritten.Append(Environment.NewLine);
}
Console.WriteLine(dataToBeWritten.ToString());
Console.ReadLine();
var testpath = #"D:\\Lutchmee2.csv";
File.WriteAllText(testpath, dataToBeWritten.ToString());
Your XElement is UpdateDB, so from that context there is no child UpdateDB. You'd have to amend your query to:
/Transaction/Insert/Set/szItemID
That said, it's unclear why you're loading the document into the DOM, converting it to a string and than parsing to an XElement. Just load into an XDocument and use your original query:
var doc = XDocument.Load(#"D:\xml_1.xml");
var val = (string) doc.XPathSelectElement("/UpdateDB/Transaction/Insert/Set/szItemID");
Or better still, use LINQ to XML as it was intended:
var val = (string) doc.Descendants("Set").Elements("szItemID").First()

Modifying element of Json string (in C#)

I'm trying to modify an attribute of an XML string using Json in C#. Currently I'm doing the following:
XmlDocument serializedFormXml = new XmlDocument();
serializedFormXml.LoadXml(mySerializedForm);
string formJsonString = JsonConvert.SerializeXmlNode(serializedFormXml, Newtonsoft.Json.Formatting.None, true);
JObject formJsonObj = JObject.Parse(formJsonString);
formJsonObj["#code"] = "myNewValue";
var xml = JsonConvert.DeserializeXmlNode(formJsonObj.ToString()).ToString();
When I do this I get get an exception on the last line:
Unable to cast object of type 'Newtonsoft.Json.Converters.XmlDocumentWrapper' to type 'Newtonsoft.Json.Converters.IXmlElement'
Any ideas what I'm doing wrong and how I can fix modify my form attribute "code"?
This is the XML I'm using:
<Form code="XYZ">
<Info>Data</Info>
.....
Thanks!
That's going to be way, way easier with Linq-to-XML:
var doc = XDocument.Parse(mySerializedForm);
doc.Root.SetAttributeValue(doc.Root.Name.Namespace + "code", "myNewValue");
var xml = doc.ToString();
This drops the XML declaration. If you need the XML declaration included, you can use the following extension method:
public static class XObjectExtensions
{
public static string ToXml(this XDocument xDoc)
{
using (var writer = new StringWriter())
{
xDoc.Save(writer);
return writer.ToString();
}
}
}
And then write:
var xml = doc.ToXml();
If specifically you need to make the encoding string say "UTF-8", use Utf8StringWriter from this answer.
Update
The reason you code fails is that you stripped the XML root element name away when you converted to json by passing true here:
string formJsonString = JsonConvert.SerializeXmlNode(serializedFormXml, Newtonsoft.Json.Formatting.None, true);
Thus you need to add it back when converting back:
var xml = JsonConvert.DeserializeXmlNode(formJsonObj.ToString(), serializedFormXml.DocumentElement.Name).ToString();

XML to BSON using C#

I want to convert a XML file to BSON. then import the BSON to MongoDB. I searched but could not find how to covert this using C#. please provide me a source code to do this using C#
Had the same Problem today.
It's for sure not the best solution, but
i solved it this way in my project and it works for what i need it:
Deserialize XML to Json
Deserialize Json to Bson
using (var reader = new StreamReader(context.Request.Body))
{
var body = reader.ReadToEnd(); // read input string
XmlDocument doc = new XmlDocument();
doc.LoadXml(body); // String to XML Document
string jsonText = JsonConvert.SerializeXmlNode(doc); //XML to Json
var bsdocument = BsonSerializer.Deserialize<BsonDocument>(jsonText); //Deserialize JSON String to BSon Document
var mcollection = Program._database.GetCollection<BsonDocument>("test_collection_05");
await mcollection.InsertOneAsync(bsdocument); //Insert into mongoDB
}

Can't seem to deserialize very simple xml using XmlSerializer in c#

I feel like I am going made. I have written a hundred deserializing routines, but this one is killing me!
Below is what I get returned from a service. A very simple array of strings...I think.
<ArrayOfstring xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<string>Action & Adventure</string>
<string>Comedy</string>
<string>Drama</string>
<string>Family</string>
<string>Horror</string>
<string>Independent & World</string>
<string>Romance</string>
<string>Sci-Fi/Fantasy</string>
<string>Thriller & Crime</string>
</ArrayOfstring>
I am using out the box deserializing
var serializer = new XmlSerializer(typeof(List<string>));
var reader = new StringReader(xmlString);
var GenreList = (List<string>)serializer.Deserialize(reader);
but I get the following error on the Deserialize line:
<ArrayOfstring xmlns='http://schemas.microsoft.com/2003/10/Serialization/Arrays'> was not expected
I have tried including the namespace and creating all manner of exotic objects in an attempt to get this to work. Crazy amount of time. In the end I have requested it in JSON and deserialised that with Json.net.
However I am curious as to what I have been doing wrong!
Of course XmlSerializer can deserialize it. All you need is to create XmlSerializer as follows
var serializer = new XmlSerializer(typeof(List<string>),
new XmlRootAttribute() { ElementName = "ArrayOfstring", Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays" });
The XML Serializer cannot deserialize a simpletype or a list of simple types without additional specification, but the DataContractReader can:
string content = #"
<ArrayOfstring xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
<string>Action & Adventure</string>
<string>Comedy</string>
<string>Drama</string>
<string>Family</string>
<string>Horror</string>
<string>Independent & World</string>
<string>Romance</string>
<string>Sci-Fi/Fantasy</string>
<string>Thriller & Crime</string>
</ArrayOfstring>";
var serializer = new DataContractSerializer(typeof(string[]));
var reader = new XmlTextReader(new StringReader(content));
var GenreList = new List<string>((string[])serializer.ReadObject(reader));
You can also use a simple class to achieve the same results. Note that I removed the namespaces from your XML file for brevity. You can implement reading of the namespaces in the serializer if you please.
public class ArrayOfstring
{
[XmlElement("string")]
public List<string> strings;
}
private void Deserialize(string xmlString)
{
var serializer = new XmlSerializer(typeof(ArrayOfstring));
var reader = new StringReader(xmlString);
var GenreList = ((ArrayOfstring) serializer.Deserialize(reader)).strings;
}
This will work
DataContractSerializer xmlSer = new DataContractSerializer(typeof(string[]));
TextReader reader=new StreamReader(xmlString);
var stringArr= (string[])xmlSer.ReadObject(reader);
List<string> listStr=new List<>();
for(var s in stringArr)
{
listStr.Add(s);
}
I realize this is an old question, but I recently ran on to the same issue and wanted to share what worked for me. I tried all the approaches outlined as potential solutions, but couldn't get any of them to work. Even specifying the namespace in the XmlRootAttribute approach would throw the "was not expected" error reported in the original problem. I was getting the ArrayOfString as a response from an API, so I used an XDocument parse approach:
List<string> lstGenre = new List<string>();
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();
XDocument xdoc = XDocument.Parse(responseString);
XNamespace ns = xdoc.Root.GetDefaultNamespace();
XElement root = xdoc.Element(XName.Get("ArrayOfString", ns.NamespaceName));
IEnumerable<XElement> list = root.Elements();
foreach (XElement element in list)
{
string item = element.Value; // <-- individual strings from the "ArrayOfString"
lstGenre.Add(item);
}

Categories

Resources