XPath with string or XmlDocument - asp.net

I'm having trouble parsing the xml returned from a web service because it's really just a string. The web service doesn't contain any method to submit the request, nor an object to handle the response, so I'm just getting the xml as a string and trying to parse it to properties in an object I've created.
I was messing around with XPath, but I'm unable to figure out how to use a string, or an XmlDocument object with Xpath. I don't have an actual xml file, just a string that I've used to create an XmlDocument object.
private void SetProperties(string _xml)
{
XmlDocument _doc = new XmlDocument();
_doc.LoadXml(_xml);
}
Any ideas as to how I can query that XmlDocument object with XPath?

SelectNodes or SelectSingleNode is a good place to start. There are examples on those pages of selecting/querying node lists from an XmlDocument.

Have you tried calling the various methods on the XmlDocument object? For example, the SelectSingleNode method takes an xpath string and returns an xmlNode.
Also, check this site for additional information: http://www.w3schools.com/

You can create a new XPathExpression object which you then do a select against the XDoc with it. Adding onto the XDocument load code you started with:
XmlDocument _doc = new XmlDocument();
_doc.LoadXml(_xml);
XPathNavigator navigator = _doc.CreateNavigator();
XPathExpression expression = navigator.Compile("/foo/bar");
XPathNodeIterator iterator = navigator.Select(expression);
while (iterator.HasNext()) {
//Do Something With iterator.Current.Value;
}

Related

simply dump write xml to screen

XML/ASP.net VB newbie here having fun can't find needle in haystack.
I just want to dump some XML to the screen! Loads of sites tell me how to iterate the nodes, xpath my way in directly. I just want the whole lot to screen.
Dim doc As New XmlDocument
doc.Load("remote.xml")
Dim writer as XmlTextWriter = new XmlTextWriter("debug.xml",nothing)
writer.Formatting = Formatting.Indented
doc.Save(writer)
Does a sterling job of getting it to a file, but I want it on the screen. doc.print(writer).....
Please help.
Try it with the innerXml of your doc. Make sure to HtmlEncode it for it to show up. Stick a literalcontrol on your aspx with id='ltXml' and then something like this:
Dim doc As New XmlDocument()
doc.Load(Server.MapPath("~/remote.xml"))
ltXml.Text = Server.HtmlEncode(doc.InnerXml)
Edited per comment by OP.
Have the function in your class return the Xml string.
Private Class [MyClass]
Public Shared Function getXml() As String
Dim doc As New XmlDocument()
doc.Load("somefile.xml")
Return HttpContext.Current.Server.HtmlEncode(doc.InnerXml)
End Function
End Class
Then in your aspx code behind of your webpage call the class function:
ltXml.Text = [MyClass].getXml()
I suggest using the modern XDocument class instead of the old, deprecated XmlDocument.
XDocument.ToString already returns a nicely formatted version of the XML, so all you need to do is:
Dim doc As XDocument = XDocument.Load("remote.xml")
Dim formatted As String = doc.ToString()

Reading posted JSON data in ASP.NET

I subscribe to a mass email service which, when an error occurs at their end, posts to a page on my website as an endpoint to notify me that an email has bounced.
They describe it as follows:
The event data is sent in the POST request body using a JSON object.
What I need to know is how can I capture the info posted to me?
Currently I'm pointing them to a generic handler, a .ashx page, this can be changed to whatever as long as it's in .NET.
In 10 years working with first classic ASP and now .NET I've never done this before and I must admit I don't even know where to start.
This is the code I used to achieve a similar thing - not sure where I got it originally.
C#
var strJSON = String.Empty;
context.Request.InputStream.Position = 0;
using (var inputStream = new StreamReader(context.Request.InputStream))
{
strJSON = inputStream.ReadToEnd();
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
object serJsonDetails = javaScriptSerializer.Deserialize(strJSON, typeof(object));
// go and process the serJsonDetails object
or VB
Dim strJSON = [String].Empty
context.Request.InputStream.Position = 0
Using inputStream = New StreamReader(context.Request.InputStream)
strJSON = inputStream.ReadToEnd()
End Using
Dim javaScriptSerializer As New JavaScriptSerializer()
Dim serJsonDetails As Object = javaScriptSerializer.Deserialize(strJSON, GetType(Object))
' go and process the serJsonDetails object
You could just read the Request stream (Request.GetRequestStream) and use Json.NET to deserialize to an object.
You could use MVC4 and the built in object mapping.
There's many options. Perhaps you should read up on them more so that you have an idea of their capabilities and drawbacks.
Probably Request.Form (here) will help you get the JSON, if you know the content of the post, and then you need something like json.net library to get the object, or you can simply search the string using regex or keywords
Or if you can direct the post to a web service(asmx) instead of a web page, those services will parse the json for you
If you need to read raw post data twice or many times, i advice you to use this code.
string postBodyJson = null;
MemoryStream ms = new MemoryStream();
Request.InputStream.Position = 0;
Request.InputStream.Seek(0, SeekOrigin.Begin);
Request.InputStream.CopyTo(ms);
ms.Position = 0;
ms.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms))
{
postBodyJson = reader.ReadToEnd();
}

Xdocument.Load(XMLReader.Read()) Is giving me erros

I am trying to load a document see the code below
try
{
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
XmlReader responseReader = XmlReader.Create(response.GetResponseStream());
XDocument docs = XDocument.Load(responseReader.Read());
The above line is telling me xdocument.Load has some invalid arguments.
//XDocument docs = XDocument.Load(response.GetResponseStream());
This line is not loading anything Docs is empty
XDocument docs = XDocument.Load(responseReader);
This line is not giving any overload errors but returning nothing.
List<string> books = docs.Descendants("Test")....."Remaining QQuery"
Change
XDocument docs = XDocument.Load(responseReader.Read());
to
XDocument docs = XDocument.Load(responseReader);
The method for XDocument will accept an XmlReader which is what responseReader is, however you are calling the .Read() method on which only returns a boolean which is why you are getting that error.
Firstly, you almost had it without the XmlReader; you can't load the response straight into the XDocument, but, most of the time you can do:
XDocument docs = XDocument.Load(new StreamReader(response.GetResponseStream()));
Then check docs.Nodes.Count.
If docs is still empty, it's time to look at the response itself. Look at the response.ContentType - what is it?
Assuming the response isn't too large, look at it! You can do:
StreamReader reader = new StreamReader(response.GetResponseSteam());
string text = reader.ReadToEnd();
You can dump that string anywhere. Alternatively, if it is very big, you can save the response to disk, using either a FileStream with your Response, or, more simply WebClient.DownloadFile(url, path_to_save)
Either should be good enough to get you one step closer.

How to call a node from a xml file within asp.net web page

I am trying to use the value of <Directory> in my following piece of code:
Public Function GetFile() As String
Dim di As New DirectoryInfo(< Directory >)
Dim files As FileSystemInfo() = di.GetFileSystemInfos()
Dim newestFile = files.OrderByDescending(Function(f) f.CreationTime).First
Return newestFile.FullName
End Function
Is there any way i can call the value stored in the xml file in my code?
Andy's answer is good, but in VB it's even easier.
Dim xmlDoc As XDocument
Dim dir as String
xmlDoc = XDocument.Load("XMLFile1.xml")
dir = xmlDoc.<ServerList>.<Server>.<Directory>.First().Value;
Or even easier if the XML file will never have more than one <Directory> element that you care about:
dir = xmlDoc...<Directory>.First().Value;
To answer your comment on Andy's answer:
dir = (From server as XElement in xmlDoc...<Server>
Where server.<ServerName>.First().Value = requiredServer
Select server.<Directory>.First().Value)(0);
As you are clearly familiar with Linq, you can operate on the Xml using System.Xml.Linq.
Apologies, this is in c#.
var xDoc = XDocument.Load("XMLFile1.xml");
var dir = xDoc.Element("ServerList").Elements("Server").Elements("Directory").First().Value;
If you have the Xml stored in a string replace XDocument.Load with XDocument.Parse.
Obviously you'll have to defend against parse errors, file missing and schema inconsistencies in your production code.
You can use this http://support.microsoft.com/kb/301225

How to parse and update xml file using xmltextreader or xmlreader

Hi i have the following code to read the xml file and change the value of particular node ,but i want to do the same using xmltextreader or xmlreader, i am trying to avoid the statement doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml")); , which has a direct reference to my physical file.
XmlDocument doc = new XmlDocument();
string xmlFile = System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml");
doc.Load(xmlFile);
XmlNodeList xmlnode = doc.GetElementsByTagName("value");
xmlnode[0].ChildNodes[0].Value = 23;
doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml"));
Well something's going to have to have a reference to the file. However, you could easily change your code to simply accept a Stream (which would have to be readable, writable and seekable):
private static void ChangeDocument(Stream stream)
{
XmlDocument doc = new XmlDocument();
doc.Load(stream);
XmlNodeList xmlnode = doc.GetElementsByTagName("value");
xmlnode[0].ChildNodes[0].Value = 23;
stream.Position = 0;
doc.Save(stream);
stream.SetLength(stream.Position); // Truncate the file if it was longer
}
It's somewhat ugly, admittedly...
Of course you could always pass in the filename itself - your MapPath call would still be in a higher level method, which may be all you're trying to achieve:
private static void ChangeDocument(string filename)
{
XmlDocument doc = new XmlDocument();
doc.Load(filename);
XmlNodeList xmlnode = doc.GetElementsByTagName("value");
xmlnode[0].ChildNodes[0].Value = 23;
doc.Save(filename);
}
One final aside - if you're using .NET 3.5 or higher, I'd strongly recommend using LINQ to XML as a rather nicer XML API.
You can not write or update XML data using XmlTextReader or XmlReader ansectors, use XmlTextWriter or XmlWriter ancestors, ot XmlSerializer.Serialize(..) method as alternative.
You can not avoid the statement and alike,
doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml"));
which has a direct reference to your physical file, because you have to write the changed nodes back to the origin file again, otherwize you have to switch your system from using file-based approach (ASP.NET web site using file-based data storage) to database-driven approach (ASP.NET web site using the database server).
As alternative, use your own XML data in your SQL server, then load and update it using EF of ORM.

Resources