Linq2Xml Parse Output from REST web service - asp.net

I am attempting to parse the XML output from a REST web service and have been pointed in the direction of using Linq2Xml to query the XML for the attributes that I am after. The XML output is as follows:
<?xml version="1.0" encoding="UTF-8"standalone="yes" ?>
<Response Status="OK">
<Item Name="NumberZones">2</Item>
<Item Name="CurrentZoneID">10001</Item>
<Item Name="CurrentZoneIndex">1</Item>
<Item Name="ZoneName0">Westralia</Item>
<Item Name="ZoneID0">0</Item>
<Item Name="ZoneGUID0">{81C56183-31DA-45C2-90C3-81609F01B38B}</Item>
<Item Name="ZoneName1">Lounge</Item>
<Item Name="ZoneID1">10001</Item>
<Item Name="ZoneGUID1">{eac0109e-0090-a992-7fba-dc67fe29e6e7}</Item>
</Response>
I am wanting to return in a datatable the ZoneID, ZoneName, and ZoneGUID, I am wanting the function to return something like:
id name guid
0 westralia {81C56183-31DA-45C2-90C3-81609F01B38B}
10001 lounge {eac0109e-0090-a992-7fba-dc67fe29e6e7}
I have been working on the following function to query the XML, and have gotten as far as attempting to return results (not even at the point of trying to manipulate the data to get it into the format that I am wanting).
Private Function getServerResponse_Linq(ByVal queryString As Uri) As DataTable
Dim dt As DataTable = New DataTable("data")
With dt
.Columns.Add("name")
.Columns.Add("Value")
End With
Dim loaded As XDocument = XDocument.Load(queryString.ToString)
Dim dr As DataRow
Dim query = From c In loaded.<Response> Select c
For Each result In query
dr = dt.NewRow
With dr
.Item("name") = result.#name
.Item("value") = result.Value
End With
Next
Return dt
End Function
The returned datatable is empty, I have confirmed that result does have the XML assigned, and result.value is the string version of the XML file (200Westralia0{81C56183-31DA-45C2-90C3-81609F01B38B}Lounge10001{eac0109e-0090-a992-7fba-dc67fe29e6e7})
Is anyone able to provide assistance in how I can read from the REST XML example above the name (ZoneName%) and the attribute value (Westralia and Lounge)?

There are three problems I can see with your code snippet. First, instead of
Dim query = From c In loaded.<Response> Select c
you need
Dim query = From c In loaded.<Response>.Elements Select c
or even just
Dim query = loaded.<Response>.Elements
to fetch the Items rather than the Response.
Also, you need to add
dt.Rows.Add(dr)
to your loop, otherwise your new row won't get added to the DataTable.
Finally, XML is case sensitive so you need to use #Name, not #name.

Related

Read xml embedded in aspx page

I want to read this source as xml
http://blabla/bla.aspxPageMethod=ElencoPresentiNew&idArea=0&dtRif=&mostra=T&format=xml
That returns a result like the following (straight in the browser, not as file)
I tried to use XmlDocument or Agilitypack tool, also httpwebrequest, but I get different problems. With xmldocument I get an error saying that some xml elements are missing, with the other methods I get the html source of the page but not the data.
How can I achieve what I want? Thanks
EDIT:
first xml lines from source:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Result>
<has_custom_url>false</has_custom_url>
<oggi>24.10.2019</oggi>
<utente>
<controlli196eseguiti>true</controlli196eseguiti>
<idprofiloutente>17</idprofiloutente>
<dizionario>
<u>U</u>
<e>E</e>
</dizionario>
<nominativo>super</nominativo>
<cambiopwd>1567402823277</cambiopwd>
<descrinsediamento>Insediamento principale</descrinsediamento>
EDIT 2:
Dim doc As XmlDocument = New XmlDocument()
doc.Load("http://192.168.2.49/checkandin/area.aspx?PageMethod=ElencoPresentiNew&idArea=0&dtRif=&mostra=T&format=xml")
Dim ns As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
Dim nodes As XmlNodeList = doc.SelectNodes("PresentiPerAreaCalc", ns)
Dim listaIniziale As New List(Of String)
For Each node As XmlNode In nodes
Dim record As String = node.SelectSingleNode("descrazienda").Value
listaIniziale.Add(record)
Next

Converting string to XML node in VB.NET

I've an XML string in database column like this
<trueFalseQuestion id="585" status="correct" maxPoints="10"
maxAttempts="1"
awardedPoints="10"
usedAttempts="1"
xmlns="http://www.ispringsolutions.com/ispring/quizbuilder/quizresults">
<direction>You have NO control over how you treat customers.</direction>
<answers correctAnswerIndex="1" userAnswerIndex="1">
<answer>True</answer>
<answer>False</answer>
</answers>
</trueFalseQuestion>
But I need to do XML operations on this string like select its name, attributes values,inner text etc. How can I make this possible from this string
EDIT
Im sharing the code snippet I tried, but not working
Dim myXML As String
Dim gDt As New DataTable
gDt.Columns.Add("id")
gDt.Columns.Add("questionid")
gDt.Columns.Add("serial")
gDt.Columns.Add("direction")
Dim dr As DataRow
myXML ='<my above shared XML>'
Dim xmlDoc As New XmlDocument
xmlDoc.LoadXml(myXML)
dr = gDt.NewRow
dr("serial") = 1
dr("id") = xmlDoc.Attributes("id").Value
dr("direction") = xmlDoc("direction").InnerText
gDt.Rows.Add(dr)
But thats not working at all as I wish
There are many ways to parse XML in .NET, such as using one of the serialization classes or the XmlReader class, but the two most popular options would be to parse it with either XElement or XmlDocument. For instance:
Dim input As String = "<trueFalseQuestion id=""585"" status=""correct"" maxPoints=""10"" maxAttempts=""1"" awardedPoints=""10"" usedAttempts=""1"" xmlns=""http://www.ispringsolutions.com/ispring/quizbuilder/quizresults""><direction>You have NO control over how you treat customers.</direction><answers correctAnswerIndex=""1"" userAnswerIndex=""1""><answer>True</answer><answer>False</answer></answers></trueFalseQuestion>"
Dim element As XElement = XElement.Parse(input)
Dim id As String = element.#id
Or:
Dim input As String = "<trueFalseQuestion id=""585"" status=""correct"" maxPoints=""10"" maxAttempts=""1"" awardedPoints=""10"" usedAttempts=""1"" xmlns=""http://www.ispringsolutions.com/ispring/quizbuilder/quizresults""><direction>You have NO control over how you treat customers.</direction><answers correctAnswerIndex=""1"" userAnswerIndex=""1""><answer>True</answer><answer>False</answer></answers></trueFalseQuestion>"
Dim doc As New XmlDocument()
doc.LoadXml(input)
Dim nsmgr As New XmlNamespaceManager(doc.NameTable)
nsmgr.AddNamespace("q", "http://www.ispringsolutions.com/ispring/quizbuilder/quizresults")
Dim id As String = doc.SelectSingleNode("/q:trueFalseQuestion/#id", nsmgr).InnerText
Based on your updated question, it looks like the trouble you were having is that you weren't properly specifying the namespace. If you use XElement, it's much more forgiving (i.e. loose), but when you use XPath to select nodes in an XmlDocument, you need to specify every namespace, even when it's the default namespace on the top-level element of the document.

Reading xmlNodeList into a Dataset using VB.NET

UPDATE:
I want to dynamically dump the XML returned into a dataset without having to write out the columns names. The data returned is in very simple format, name of column, the data, then close of the name of column. Like this:
<runsql>
<cst_id>0005675667</cst_id>
<ind_last_name>Abe</ind_last_name>
<ind_first_name>Adam</ind_first_name>
<cst_ixo_title_dn/>
<cst_org_name_dn>Acme University</cst_org_name_dn>
<cst_eml_address_dn>Adam#acmeu.edu</cst_eml_address_dn>
</runsql>
I've been using a standard format to access our web services and return specific fields. I'm needing to modify this to dump the whole XML feed into an internal Dataset in VB.NET. This web service is pre-defined in my Web References section. I am successful with below code, but can't figure out a way, after much Googling and testing, to dynamically load all the columns into a Dataset. Can I get help using this format below to load into a Dataset?
Dim proxy As New myWS.netFORUMXMLWebServices
Dim strInSQL As String
Dim strOutXML2 As XmlDocument
strOutXML2 = New XmlDocument
Dim oNode2 As XmlNode
Dim oResultsNode2 As XmlNode
strInSQL = "SELECT cst_eml_address_dn FROM WebServicesTable"
strOutXML2.LoadXml("<myResults></myResults>")
oResultsNode2 = proxy.runsql(strInSQL)
Dim xmlNewDoc As XmlDocument
xmlNewDoc = New XmlDocument
xmlNewDoc.LoadXml(oResultsNode2.OuterXml)
strOutXML2.DocumentElement.AppendChild(strOutXML2.ImportNode(xmlNewDoc.DocumentElement, True))
Dim oResultsNodeList2 As XmlNodeList
oResultsNodeList2 = xmlNewDoc.SelectNodes("//runsql")
For Each oNode2 In oResultsNodeList2
returnedEmail = oNode2.SelectSingleNode("cst_eml_address_dn").InnerText
Next
And in case you were wondering the "runsql" is the parameter at the end of our web services that our vendor gave us. (webservices.asmx?op=runsql)
Basically, you just need to load the XMLDocument using DataSet.ReadXML. Here is one way:
' build xmlDoc to stand in for [proxy.runsql] return
Dim xdoc As New XmlDocument
' xml literal for the data
Dim x = <Document>
<Employee>
<Name>Ziggy Foobar</Name>
<HireDate>2/11/2010</HireDate>
</Employee>
<Elements>
<Name>Helium</Name>
<Symbol>He</Symbol>
</Elements>
<Employee>
<Name>Zoey Foobaz</Name>
<HireDate>2/11/2013</HireDate>
</Employee>
<runsql>
<cst_id>0005675667</cst_id>
<ind_last_name>Abe</ind_last_name>
<ind_first_name>Adam</ind_first_name>
<cst_ixo_title_dn/>
<cst_org_name_dn>Acme University</cst_org_name_dn>
<cst_eml_address_dn>Adam#acmeu.edu</cst_eml_address_dn>
</runsql>
</Document>
' load litersl to XmlDocument
xdoc.LoadXml(x.ToString)
'***** xdoc is now a stand in for the return from [proxy.runsql]
Dim ds As New DataSet
' load xdoc to dataset via node reader
Using xnr As New XmlNodeReader(xdoc)
ds.ReadXml(xnr) ' this is what you want
End Using ' dispose of node reader
Dim n As Integer ' test/view DS result
' verify: 2 tables?
For Each t As DataTable In ds.Tables
Console.WriteLine("Table: " & t.TableName)
' we know there are 2, just verifying
Console.WriteLine("Column Names: {0}, {1}", t.Columns(0).ColumnName,
t.Columns(1).ColumnName)
n = 1
For Each r As DataRow In t.Rows
' demo there only 2 cols
Console.WriteLine("[Item {0}]: {1}, {2}", n.ToString,
r(0).ToString, r(1).ToString)
n += 1
Next
Console.WriteLine()
Next
The end result is 3 tables in the DS, with the noncontiguous Employee data glued back together. There is no need to specify table or column names, it parses them itself. In your case, you could ignore any other tables in the DataSet other than "runsql". I pasted your runsql block after the test code was written, so some of the "only 2 columns" comments are wrong. Output:
Table: Employee
Column Names: Name, HireDate
[Item 1]: Ziggy Foobar, 2/11/2010
[Item 2]: Zoey Foobaz, 2/11/2013
Table: Elements
Column Names: Name, Symbol
[Item 1]: Helium, He
Table: runsql
Column Names: cst_id, ind_last_name
[Item 1]: 0005675667, Abe
Works on My MachineTM

NullReference on a value that is not null

I have a function that gets a string passed to it. When testing the function, I'm getting a null reference exception on the string parameter that gets passed to it, even though the string is not null, I don't understand why I'm getting this error. I have a screen shot below
I used a dummy value to verify both the string parameter in the SelectSingleNode function and the newValue string parameter being passed to my function and they both contain values, so I don't understand why it's throwing a null reference exception. Just for clarity, the purpose of the function is to write values back to the nodes of an XML file.
UPDATE
Sorry for not posting code
Private Sub setValue(ByVal nodeToMod As String, ByVal newValue As String)
''Test writing to xml config file
Dim dummy As String = "Config/" & nodeToMod
Dim xmlDoc As New XmlDocument
Using fs As FileStream = New FileStream(HttpContext.Current.Server.MapPath("~/XML_Config/Config.xml"), FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
xmlDoc.Load(fs)
Dim foo As XmlNode = xmlDoc.SelectSingleNode(dummy)
Console.WriteLine(foo.InnerXml)
fs.Seek(0, SeekOrigin.Begin)
fs.SetLength(0)
xmlDoc.Save(fs)
End Using
End Sub
And here is the XML file I'm working with
<?xml version="1.0" encoding="utf-8"?>
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Username>john.doe#email.com</Username>
<Password>Password1</Password>
<ProductType>MyProduct</ProductType>
<DirectoryEntryPath>LDAP://myDomain</DirectoryEntryPath>
<SMTPDefaultOnly>True</SMTPDefaultOnly>
<Logo>myLogo.gif</Logo>
</Config>
Yes, the SlectSingleNode function is not returning a value. I just started working with XPath, this seemed to have worked when I was using last week. I'm not sure why it has stopped working now.
UPDATE2:
Got it, stupid mistake. I had nodeToMod being passed as "UserName" instead of "Username" in the Set method
Set(ByVal value As String)
setValue("UserName", value.ToString)
_userName = value
End Set
The null reference that is being complained about is the result of the call to SelectSingleNode. That is, when the xpath formed by concatenating /Config/ and the contents of nodeToMod is evaluated against the document, no node matches. So you get null, and attempting to set the InnerText of null gives the exception.
We would really need to see nodeToMod and the xml file itself to help further. Also, please post code rather than screenshots!
Ensure that the FileStream object you're creating doesn't come out null. Maybe it can't find the config.xml file?
It's likely that the result of SelectSingleNode is null.
Change that line to two lines, and it will be easier to see the problem in the debugger:
Dim node = xmlDoc.SelectSingleNode(dummy)
node.InnerText = newValue

Error when trying to load XML from a Sharepoint Web Services call into an ASP.NET Gridview

I'm getting the error:
Illegal characters in path.
when trying to load XML, using XPath, into a gridview's datasource in the PageLoad function in the code-behind of an ASP.NET page I'm building. Does anyone know what this error means?
The XML coming in from the Sharepoint Web Services call is:
<?xml version='1.0' encoding='ISO-8859-1'?>
<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="2">
<z:row ows_Attachments="0" ows_LinkTitle="testTitle" ows_IncidentID="0" .../>
<z:row ows_Attachments="0" ows_LinkTitle="test2" ows_IncidentID="1" ... />
</rs:data>
And my code behind is:
newNode = thisL.GetListItems(strID, viewName, query, viewFields, rowLimit, queryOptions, webID)
mNodeList = newNode.ChildNodes
Dim ds_me As New Data.DataSet
xdsIncidents.Data = "<?xml version='1.0' encoding='utf-8'?>" & newNode.OuterXml
xdsIncidents.XPath = "//z:row"
GridView1.AutoGenerateColumns = True
DataDiv.InnerText = xdsIncidents.Data
ds_me.ReadXml(xdsIncidents.Data)
Dim dv As New Data.DataView(ds_me.Tables(1))
GridView1.DataSource = dv
GridView1.DataBind()
The error message is coming up on the line "ds_me.ReadXML..."
This is because that overload of ReadXml is expecting a file path to read some xml from, not a string with xml in it.
You'll need to create an XmlReader or TextReader from your string if you want to load the DataSet in this way.

Resources