How to pull out of xml-file - c#

Via GET-request I got next xml code:
<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Translation code=\"200\"lang=\"en-ru\"><text>Sample</text></Translation>
So in particular I need to "stretch out" word "Sample". How?
Is this considering as deserialization?

Implemented with next code:
if (response.StatusCode == HttpStatusCode.OK)
{
HttpContent responseContent = response.Content;
var json = await responseContent.ReadAsStringAsync();
XmlDocument doc = new XmlDocument();
doc.LoadXml(json);
var text = doc.GetElementsByTagName("text")[0].InnerText;
}
Output: Sample

Related

Deserialize XML to string/object/List of objects from HTTP response

I have a Xamarin.Forms App and get a response.Content in XML format. How to Deserialize the data in different types in different responses ex. string , object , list .
This is my code:
client.DefaultRequestHeaders.Clear();
var response = await client.GetAsync($"api/users");
if (response.IsSuccessStatusCode)
{
var pom = await response.Content.ReadAsStringAsync();
///// xml logic here
return pom;
}
else
{
return null;
}
UPDATE
I receive : <test> TEst </test>
how to convert that?

XML from URL - Data at the root level is invalid. Line 1, position 1 Why it works with one URL and not the other?

As far as I can tell, these two end points are both valid XML output. However when I use the same code on the second end point I get the error:
Data at the root level is invalid. Line 1, position 1
Here is my code:
//Works
XmlDocument testDocument = new XmlDocument();
testDocument.Load("https://www.w3schools.com/xml/note.xml");
//Fails
XmlDocument testDocumentTwo = new XmlDocument();
testDocumentTwo.Load("https://www.domainNameHere.com/direct/umbraco/api/productsearch/NameSearch?countryCode=en-gb");
I opened Fiddler and watched the request and its response, and lo and behold your endpoint is returning JSON, not XML:
If I use HttpClient to set an explicit Accept header, then I get XML back and everything works:
using var client = new HttpClient();
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "https://www.clinigengroup.com/direct/umbraco/api/productsearch/NameSearch?countryCode=en-gb");
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
var response = await client.SendAsync(requestMessage);
var xml = await response.Content.ReadAsStringAsync();
XmlDocument testDocumentTwo = new XmlDocument();
testDocumentTwo.LoadXml(xml);

How to return GetResponseStream in xml?

I am trying to create web request, which sends XML via POST call and would like to return the response back in XML.
I am having a little difficulty with the response back xml, as I am little I unsure how do I set that up int he code below. here is my attempt:
// Attempt to receive the WebResponse to the WebRequest.
using (HttpWebResponse hwresponse = (HttpWebResponse)hwrequest.GetResponse())
{
statusCode = (int)hwresponse.StatusCode;
if (hwresponse != null)
{ // If we have valid WebResponse then read it.
using (StreamReader reader = new StreamReader(hwresponse.GetResponseStream()))
{
// XPathDocument doc = new XPathDocument(reader);
string responseString = reader.ReadToEnd();
if (statusCode == 201 )
{
// var response = new XElement("Status",
// new XElement("status_code", statusCode),
// new XElement("resources_created",
//// new XElement("Link"),
// new XElement("href"),
// new XElement("title")
// ),
// new XElement("warnings")
// );
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(responseString);
XmlNodeList address = xmlDoc.GetElementsByTagName("Status");
responseData = xmlDoc.ToString();
reader.Close();
}
}
}
hwresponse.Close();
}
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.ProtocolError)
{
// XmlDocument xmlDoc = new XmlDocument();
// XmlNodeList address = xmlDoc.GetElementsByTagName("Status", statusCode);
// xmlDoc.Load(xmlDoc);
}
// if (e.Status == WebExceptionStatus.ProtocolError)
// {
// responseData = "Status Code : {0}" + ((HttpWebResponse)e.Response).StatusCode + "Status Description : {0}" + ((HttpWebResponse)e.Response).StatusDescription;
// responseData "Status Description : {0}" + ((HttpWebResponse)e.Response).StatusDescription;
// }
}
I would like to be able to return the response back in the following XML format:
<status>
<status_code>201</status_code>
<etag>12345678</etag>
<resources_created>
<link
rel="http://api-info.com"
href="http://api-info.com/tag/Some%20Tag"
title="Subscriber Tag (Some Tag)" />
</resources_created>
<warnings>
<warning>Some Warning Message</warning>
</warnings>
</status>
I would also like to ask, if my 'StatusCode' should be setup as if conditions or try&catch.
Any guide would be most helpful. Many thanks.
You may not have any control over what is sent to you but you can ask for xml with an Accept header.
hwrequest.Accept = "application/xml";
However, you will have no control over the structure.
Yes, you should handle the response status (200, 201, 404 etc.) using If/Else statements and NOT rely on try/catch to handle your logic. Try/Catch is for error handling, and not a place to handle regular application flow.
For the Web Requests you are using an obsolete API. Unless there is a specific limitation that forces you to use HttpWebRequest and HttpWebResponse, you should use a newer (and simpler) API like WebClient or HttpClient (only .NET 4.5).
http://msdn.microsoft.com/en-us/library/system.net.webclient%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.118%29.aspx
For response handling i would advice using Linq to XML instead of the old XmlDocument API.
If your response XML has the "status" element at the root of the XML document, then you can do:
var xmlDoc = XDocument.Load(reader);
var statusXml = xmlDoc.ToString();
If the "status" element is a children of another root XML element, then you can do:
var xmlDoc = XDocument.Load(reader);
var statusElement = xmlDoc.Root.Element("status");
var statusXml = statusElement.ToString();
If you still want to use the old HTTP API, You can get rid of
string responseString = reader.ReadToEnd();
and pass directly the StreamReader in the XDocument.Load method as in my example.
In case you upgrade your solution to use e.g. WebClient you can use the DownloadString() method, and then load the string result into the XDocument.Load() method.

How to send XML content with HttpClient.PostAsync?

I am trying to fulfill this rest api:
public async Task<bool> AddTimetracking(Issue issue, int spentTime)
{
// POST /rest/issue/{issue}/timetracking/workitem
var workItem = new WorkItem(spentTime, DateTime.Now);
var httpContent = new StringContent(workItem.XDocument.ToString());
var requestUri = string.Format("{0}{1}issue/{2}/timetracking/workitem", url, YoutrackRestUrl, issue.Id);
var respone = await httpClient.PostAsync(requestUri, httpContent);
if (!respone.IsSuccessStatusCode)
{
throw new InvalidUriException(string.Format("Invalid uri: {0}", requestUri));
}
return respone.IsSuccessStatusCode;
}
workItem.XDocument contains the following elements:
<workItem>
<date>1408566000</date>
<duration>40</duration>
<desciption>test</desciption>
</workItem>
I am getting an error from the API: Unsupported Media Type
I really have no idea how to resolve this, help is greatly appreciated. How do I marshall an XML file via a HTTP POST URI, using HttpClient?
You might want to set the mediaType in StringContent like below:
var httpContent = new StringContent(workItem.XDocument.ToString(), Encoding.UTF8, "text/xml");
OR
var httpContent = new StringContent(workItem.XDocument.ToString(), Encoding.UTF8, "application/xml");
You could use
var respone = await httpClient.PostAsXmlAsync(requestUri, workItem);
https://msdn.microsoft.com/en-us/library/system.net.http.httpclientextensions_methods
To use Matt Frear's solution you may need to add NuGet Package:
Microsoft.AspNet.WebApi.Client
This brings in the extension methods so you can use:
var respone = await httpClient.PostAsXmlAsync<WorkItem>(requestUri, workItem);
This works for the newer .Net 5 so assume will work for asp.net core 3.1.
The accepted answer doesn't include the XML declaration, which may or may not matter. Below is a simple extension method for XDocument that prepends the XML declaration. Otherwise, the technique is identical:
// Extension method
public static string ToStringWithDeclaration(this XDocument doc, string declaration = null)
{
declaration ??= "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n";
return declaration + doc.ToString();
}
// Usage (XDocument -> string -> UTF-8 bytes)
var content = new StringContent(doc.ToStringWithDeclaration(), Encoding.UTF8, "text/xml");
var response = await httpClient.PostAsync("/someurl", content);
If you want, you can also skip the step of converting the XDocument to a string (which is UTF-16 encoded), and just go right to UTF-8 bytes:
// Extension method
public static ByteArrayContent ToByteArrayContent(
this XDocument doc, XmlWriterSettings xmlWriterSettings = null)
{
xmlWriterSettings ??= new XmlWriterSettings();
using (var stream = new MemoryStream())
{
using (var writer = XmlWriter.Create(stream, xmlWriterSettings))
{
doc.Save(writer);
}
var content = new ByteArrayContent(stream.GetBuffer(), 0, (int)stream.Length);
content.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
return content;
}
}
// Usage (XDocument -> UTF-8 bytes)
var content = doc.ToByteArrayContent();
var response = await httpClient.PostAsync("/someurl", content);
// To view the serialized XML as a string (for debugging), you'd have to do something like:
using var reader = new StreamReader(content.ReadAsStream());
string xmlStr = reader.ReadToEnd();
For a third option, XDocument.Save/XmlWriter can also output to a string via StringBuilder (as shown in the documentation). That is useful if you want a string but need control over formatting (such as whether to use indentation). Just be aware that the XML declaration generated via this method will always say "utf-16" (regardless of XmlWriterSettings.Encoding), so you probably want to specify XmlWriterSettings.OmitXmlDeclaration = true and add the declaration manually afterward. See this question for some discussion of that issue.

Converting JSON to XML

I trying to convert JSON output into XML. Unfortunately I get this error:
JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifing a DeserializeRootElementName.
This is what I up to now created.
string url = string.Format("https://graph.facebook.com/{0}?fields=posts.fields(message)&access_token={1}", user_name, access_token);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
jsonOutput = reader.ReadToEnd();
Console.WriteLine("THIS IS JSON OUTPUT: " + jsonOutput);
}
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(jsonOutput);
Console.WriteLine(doc);
And this is my JSON output:
{"id":"108013515952807","posts":{"data":[{"id":"108013515952807_470186843068804","created_time":"2013-05-14T20:43:28+0000"},{"message":"TEKST","id":"108013515952807_470178529736302","created_time":"2013-05-14T20:22:07+0000"}
How can I solve this problem?
Despite the fact your JSON provided in the question is not complete, you have multiple properties at the top level as indicated by the exception. You have to define the root for it to get valid XML:
var doc = JsonConvert.DeserializeXmlNode(jsonOutput, "root");
EDIT: In order to print out your XML with indentation you can use XDocument class from System.Xml.Linq namespace: XDocument.Parse(doc.InnerXml).
I thought it's worth linking to the Documentation for turning xml to json and the other way around.
The guys are right..
// To convert an XML node contained in string xml into a JSON string
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
// To convert JSON text contained in string json into an XML node
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);
You can do JSON-to-XML also by using the .NET Framework (System.Runtime.Serialization.Json):
private static XDocument JsonToXml(string jsonString)
{
using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(jsonString)))
{
var quotas = new XmlDictionaryReaderQuotas();
return XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(stream, quotas));
}
}
DeserializeXmlNode returns XDcument.
If needed XNode use FirstNode.
//string jsonOutput="{"id":"108013515952807","posts":{"data":[{"id":"108013515952807_470186843068804","created_time":"2013-05-14T20:43:28+0000"},{"message":"TEKST","id":"108013515952807_470178529736302","created_time":"2013-05-14T20:22:07+0000"}";
var myelement= JsonConvert.DeserializeXmlNode(jsonOutput, "myelement").FirstNode;
Your shared JSON is invalid please go through http://jsonformatter.curiousconcept.com/ and validate your JSON first.
Yourt JSON should look like:
{
"id":"108013515952807",
"posts":{
"data":[
{
"id":"108013515952807_470186843068804",
"created_time":"2013-05-14T20:43:28+0000"
},
{
"message":"TEKST",
"id":"108013515952807_470178529736302",
"created_time":"2013-05-14T20:22:07+0000"
}
]
}
}
Adding on #jwaliszko's answer, converting json to XDocument:
XDocument xml = JsonConvert.DeserializeXNode(json);

Categories

Resources