I have some code:
WebRequest request = HttpWebRequest.Create(url);
WebResponse response = request.GetResponse();
using (System.IO.StreamReader sr =
new System.IO.StreamReader(response.GetResponseStream()))
{
System.Xml.Linq.XDocument doc = new System.Xml.Linq.XDocument();
doc.Load(new System.IO.StringReader(sr.ReadToEnd()));
}
I can't load my response in my XML document. I get the following error:
Member 'System.XMl.Linq.XDocument.Load(System.IO.TextReader' cannot be accessed
with an instance reference; qualify it with a type name instead.
This is becoming really frustrating. What am I doing wrong?
Unlike XmlDocument.Load, XDocument.Load is a static method returning a new XDocument:
XDocument doc = XDocument.Load(new StringReader(sr.ReadToEnd()));
It seems pretty pointless to read the stream to the end then create a StringReader though. It's also pointless creating the StreamReader in the first place - and if the XML document isn't in UTF-8, it could cause problems. Better:
For .NET 4, where there's an XDocument.Load(Stream) overload:
using (var response = request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
var doc = XDocument.Load(stream);
}
}
For .NET 3.5, where there isn't:
using (var response = request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
var doc = XDocument.Load(XmlReader.Create(stream));
}
}
Or alternatively, just let LINQ to XML do all the work:
XDocument doc = XDocument.Load(url);
EDIT: Note that the compiler error did give you enough information to get you going: it told you that you can't call XDocument.Load as doc.Load, and to give the type name instead. Your next step should have been to consult the documentation, which of course gives examples.
Related
I want to deserialize an xml with this code:
XmlSerializer serializer = new XmlSerializer(typeof(TrafficJunctions));
using (StringReader reader = new StringReader(XmlPath))
{
var test = (TrafficJunctions)serializer.Deserialize(reader);
}
But get the following exception:
XmlException: Data at the root level is invalid. Line 1, position 1.
Apparently there is a BOM at the beginning of the xml. I know that I have to remove it, but I don't understand how to do it for before deserialization. Any help is welcome.
Thanks in advance.
Solution (Credit to canton7):
XmlSerializer serializer = new XmlSerializer(typeof(TrafficJunctions));
using (StreamReader reader = new StreamReader(XmlPath))
{
var test = (TrafficJunctions)serializer.Deserialize(reader);
}
I have following url which returns me XML response in c#:
http://www.bnr.ro/files/xml/years/nbrfxrates2017.xml
Now, i want to retrieve the currency in Euro for my date which is present as a paramater in my function. I want to use Linq but i have some problems
My function:
public static void getXml(String year, String data)
{
WebClient webClient = new WebClient();
string url = "http://www.bnr.ro/files/xml/years/nbrfxrates" + year + ".xml";
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(response.GetResponseStream());
XElement xe = XElement.Load(response.GetResponseStream());
var x = (from e in xe.Elements("Cube")
where e.Attribute("date").Value.Equals(data)
select e.Element("Rate") into p
where p.Element("currency").Value.Equals(data)
select p.Value);
Console.WriteLine(x.ToString());
}
My error is:
The root element is missing on XElement xe =
XElement.Load(response.GetResponseStream());
Method GetResponseStream returns a stream:
Gets the stream that is used to read the body of the response from the
server.
You cannot read this stream twice. When you load XmlDocument it reads data from network stream and closes it releasing the connection. When you try to load XElement from the closed stream, you get an error.
You should read response stream only once - e.g. into string or into MemoryStream:
string xml;
using(var reader = new StreamReader(r.GetResponseStream()))
xml = reader.ReadToEnd();
Note: It's not clear why you need XmlDocument if you are using linq to xml.
I have XML with the element: <DESCRIPTION>fault – No reply</DESCRIPTION>
I am transforming the Xml from a web-service as follows based on Jon Skeet's code https://stackoverflow.com/a/427737/197229 (the original Xml validates fine):
public sealed class StringWriterUTF8 : StringWriter
{
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader streamReader = new StreamReader(stream);
string xml = streamReader.ReadToEnd();
logger.Log().Debug(String.Format("Received Xml:\n{0}", xml));
if(Transform != null)
{
using (var stringReader = new StringReader(xml))
using (var xmlReader = XmlReader.Create(stringReader))
using (var stringWriter = new StringWriterUTF8())
using (var xmlTextWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings()
{ Indent= true}))
{
Transform.Transform(xmlReader,xmlTextWriter);
xml = stringWriter.ToString();
logger.Log().Debug(String.Format("Transformed Xml:\n{0}", xml));
}
}
Everything looks great... but the generated XML is failing validation when I try to use it, even though to the naked eye it looks fine. If I remove that hyphen, there are no problems.
I don't understand why the original XML is fine and the .Net classes are getting tripped up, but if I try and validate the Xml in Notepad++ I get this:
Input is not proper UTF-8, indicate encoding ! Bytes: 0x96 0x20 0x4E
0x6F
How can I resolve this? All I want to do is receive Xml and transform it to a new Xml file without encoding weirdness!
I use the StreamReader class to obtain XML for my GeoCoding process from Google.
StreamReader srGeoCode = new StreamReader(WebRequest.Create(Url).GetResponse().GetResponseStream());
String GeoCodeXml = srGeoCode.ReadToEnd();
XmlDocument XmlDoc = new XmlDocument();
GeoCode oGeoCode = new GeoCode();
XmlDoc.Load(GeoCodeXml);
I get XML back but it adds \n and other extras to the XML
<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<kml xmlns=\"http://earth.google.com/kml/2.0\"><Response>\n <name>
I have the same code in VB and it does not do this. I can successfully GeoCode my information using the VB version of this console app.
Is there a reason the C# version adds this extra data to the XML that I retrieve back? I am trying my best to convert everything over to C#. I enjoy coding in it over VB.
Here is the VB Code:
Dim wreqGeoCode As WebRequest = WebRequest.Create(strURL)
Dim wresGeoCode As WebResponse = wreqGeoCode.GetResponse
Dim srGeoCode As New StreamReader(wresGeoCode.GetResponseStream())
Dim strXML As String = srGeoCode.ReadToEnd()
Dim xmlDoc As New XmlDocument
xmlDoc.LoadXml(strXML)
You need XmlDoc.LoadXml if you're going to load a string. Load loads from a file.
BTW, the alternative is also more efficient. You can load the document directly from the stream:
WebRequest webRequest = WebRequest.Create(Url);
using (WebResponse webResponse = webRequest.GetResponse())
{
using (Stream responseStream = webResponse.GetResponseStream())
{
XmlDocument XmlDoc = new XmlDocument();
GeoCode oGeoCode = new GeoCode();
XmlDoc.Load(responseStream);
}
}
The using statements ensure that the WebResponse and Stream get cleaned up, even if an exception is thrown.
y not just do
GeoCodeXml=GeoCodeXml.Replace("\n","");
if it is truly returning the \n as mentioned here.
Usually I was doing something like that (just a example):
using (Stream xmlStream = client.OpenRead(xmlUrl))
{
using (XmlTextReader xmlReader = new XmlTextReader(xmlStream))
{
}
}
Isn't better to do just:
using (XmlTextReader xmlReader = new XmlTextReader(client.OpenRead(xmlUrl)))
{
}
But I'm not sure if in this short syntax all resources will be disposed (Stream) or only XmlTextReader?
Thanks in advance for your answer.
No; that won't guarantee that the Stream is disposed if the XmlTextReader constructor throws an exception. But you can do:
using (Stream xmlStream = client.OpenRead(xmlUrl))
using (XmlTextReader xmlReader = new XmlTextReader(xmlStream))
{
// use xmlReader
}
With C# 8 you can get rid of even the single nesting level:
private static void NewMultipleUsingDeclarations()
{
using var xmlStream = client.OpenRead(xmlUrl);
using var xmlReader = new XmlTextReader(xmlStream);
// use xmlReader
}
Internally the compiler creates an equivalent try catch as with the indented version and disposes of both the stream and the reader at the end of the scope of the using variables, in this case, at the end of the method.
See more:
A more detailed description in Christian Nagel's blog on the new using declaration
The official documentation.
What about (I use this now):
using (Stream xmlStream = client.OpenRead(xmlUrl))
using (XmlTextReader xmlReader = new XmlTextReader(xmlStream))
{
...
}
The second using is the referenced using from the first - no need to have brackets.
The reference documentation indicates that the object to be disposed must be declared in the using statement. Since there is no declaration for the stream, the Dispose method will not be called.
In your case you could skip the stream entirely, though, and use the constructor for the TextReader that takes a url parameter. The underlying stream will be closed when the reader is disposed.
using (var xmlReader = new XmlTextReader( xmlUrl ))
{
...
}