Retrieving data from xml using xmlDocument, xmlNode and xmlNodelist - vb.net

This is a sample code in vb.net in which i retrieve the details of elements without attributes.
For Each standardItemInfoNode In ItemInfoNodes
baseDataNodes = ItemInfoNodes.ChildNodes
bFirstInRow = True
For Each baseDataNode As XmlNode In baseDataNodes
If (bFirstInRow) Then
bFirstInRow = False
Else
Response.Write("<br>")
End If
Response.Write(baseDataNode.Name & ": " & baseDataNode.InnerText)
Next
Next
How can i retrieve the details of the xml like having node with attributes and its child also having attributes. I need to retrieve all the attributes of node and its child node which are present in the middle of other xml tags.

I'm not sure exactly what you're asking, and I can't give you a specific example without knowing the format of the XML you are trying to process, but I think what you are looking for is the Attributes property of the XmlNode objects. Each XmlNode has an Attributes property that allows you to access all the attributes for that node. Here's the MSDN page that explains it (and provides a simple example):
http://msdn.microsoft.com/en-us/library/7f285y48.aspx
EDIT:
Using the example XML you posted in the comment, you could read the all the values and attributes like this:
Dim doc As XmlDocument = New XmlDocument()
doc.LoadXml("<EventTracker><StandardItem><Header1>Header1 Text</Header1> <Header2>Header2 Text</Header2></StandardItem><Item> <Events> <EventSub EventId='73' EventName='Orchestra' Description='0'> <Person PersonId='189323156' PersonName='Chandra' Address='Arunachal'/><Person PersonId='189323172' PersonName='Sekhar' Address='Himachal'/></EventSub> </Events> </Item> </EventTracker>")
Dim header1 As String = doc.SelectSingleNode("EventTracker/StandardItem/Header1").InnerText
Dim header2 As String = doc.SelectSingleNode("EventTracker/StandardItem/Header2").InnerText
For Each eventSubNode As XmlNode In doc.SelectNodes("EventTracker/Item/Events/EventSub")
Dim eventId As String = eventSubNode.Attributes("EventId").InnerText
Dim eventName As String = eventSubNode.Attributes("EventName").InnerText
Dim eventDescription As String = eventSubNode.Attributes("Description").InnerText
For Each personNode As XmlNode In eventSubNode.SelectNodes("Person")
Dim personId As String = personNode.Attributes("PersonId").InnerText
Dim personName As String = personNode.Attributes("PersonName").InnerText
Dim personAddress As String = personNode.Attributes("Address").InnerText
Next
Next
However, if you are loading all the data in the XML like this, I would recommend deserializing the XML into an EventTracker object. Or, as I said in my comment on your post, if the only purpose for reading the XML document is to transform it into another XML or HTML document, I would recommend using XSLT, instead.
If you want to test if an attribute exists, you can do something like this:
Dim attribute As XmlNode = personNode.Attributes.GetNamedItem("PersonId")
If attribute IsNot Nothing Then
Dim personId As String = attribute.InnerText
End If
However, this would be much easier with serialization since the deserialized object would simply have null properties for any elements that didn't exist.

You can use SelectSingleNode("XPath or NodeName") and loop through the Attributes.Item(index) on that node. You can also, if you know the childnode name in advance, loop through SelectSingleNode("XPath Or NodeName").SelectSingleNode("XPath or ChildName").Attributes.Item(index).

Related

How can I populate XML with Data in vb.net

I have a some XML like below sample which i need to add values/data for the elements. What is the best way to do so short of building a string like
mystr += "<HDR>" & vbCrLf
mystr += "<MESSAGE_ID>" & trim(myMessageID) & "</MESSAGE_ID>" & vbCrLf
mystr += .... and so on
This is what my XML looks like just for reference
<HDR>
<MESSAGE_ID></MESSAGE_ID>
<CCNA></CCNA>
<MSG_TIMESTAMP></MSG_TIMESTAMP>
<TXNUM></TXNUM>
<TXTYP></TXTYP>
<TXACT></TXACT>
<RVER></RVER>
<TEST_PROD_INDICATOR></TEST_PROD_INDICATOR>
</HDR>
The easiest to use way is to use Linq to XML which offers XElement to to represent elements. The elements can be nested to create structures in code that look very similiar to what you have as an XML Document.
Here is a simple example using your sample data with nested elements and the message id set for demonstration purposes.
Sub Main
Dim hdr = New XElement("HDR",
New XElement("MESSAGE_ID", 999999),
New XElement("CCNA"),
New XElement("MSG_TIMESTAMP"),
New XElement("TXNUM"),
New XElement("TXTYP"),
New XElement("TXACT"),
New XElement("RVER"),
New XElement("TEST_PROD_INDICATOR")
)
Console.WriteLine(hdr.ToString())
End Sub
The three most important classes are XDocument, XElement and XAttribute.

How to read attribute value of xml

How can i read attribute value of a xml.
I have this below xml and i am working with windows forms vb.net
I tried something like this below but does not work. I want to read connection string value
Dim xe As XElement = XElement.Load("..\\..\\KMMiddleTier.xml")
Dim name = From nm In xe.Elements("ConnectionKey") Where nm.Element("ConnectionKey").Attribute("Key") = "DB_DEV" Select nm.Element("ConnectionKey").Attribute("ConnectionString").Value.FirstOrDefault()
Dim xmlDoc as XMLDocument
Dim xmlNodeList As XmlNodeList = xmlDoc.SelectNodes("/KMMiddleTierSecurity/ConnectionKeys/ConnectionKey")
Dim strConnectionKey As String = xmlNodeList.Item(0).Attributes("ConnectionString").Value''''
This might help.

Read a parent and child node from xml

I am trying to get 2 values out of an XML.
Currently, when I run the code below, I get just the information in "OutTime". I know why this is happening, but I am unsure how to change it to get the information I would like.
What I would like displayed is: All names under the 'People' and the 'OutTime'.
Example:
OutPut:
S7-JEHILL 20:47
XML Sheet
<Times>
<People>
<S7-JEHILL>
<OutTime>20:47</OutTime>
</S7-JEHILL>
</People>
</Times>
Current Code
Dim xmlDoc As New XmlDocument()
xmlDoc.Load("C:\Users\jefhill\Desktop\TimeStamps.xml")
Dim child As XmlNode = xmlDoc.SelectSingleNode("/Times/People")
If Not (child Is Nothing) Then
Dim nr As New XmlNodeReader(child)
While nr.Read()
NameList.Items.Add(nr.Value)
End While
End If
Add System.XML to your Reference. This is just another approach for XML file nodes manipulation.
Dim xmlDoc As New XmlDocument 'For loading xml file to read
Dim ArticleNodeList As XmlNodeList 'For getting the list of main/parent nodes
xmlDoc.Load("C:\Users\jefhill\Desktop\TimeStamps.xml") 'loading the xml file, insert your file here
ArticleNodeList = xmlDoc.GetElementsByTagName("People") 'Setting all <People> node to list
For Each articlenode As XmlNode In ArticleNodeList 'Looping through <People> node
For Each basenode As XmlNode In articlenode 'Looping all <People> childnodes
Dim result As String = ""
result = basenode.Name 'use .name to get the xml node name
For Each Node As XmlNode In basenode 'Looping all childnodes of basenode
result = result & " " & Node.InnerText 'use .Innertext to get the xml node value
Next
NameList.Items.Add(result) 'Adding Value to your variable
Next
Next
First use an XPath query to get all nodes under the tag. Then use the ChildNodes collections to get the relevant information of a) the tag name and b) the OutTime value:
Sub Main()
Dim Xml As String = "<Times><People><S7-JEHILL><OutTime>20:47</OutTime></S7-JEHILL></People></Times>"
Dim Doc As New Xml.XmlDocument
Dim Xpath As String = "/Times/People"
Dim ElementList As Xml.XmlNodeList = doc.SelectNodes(xpath)
Dim PersonName, OutTime As String
'load xml to document
Doc.LoadXml(Xml)
'iterate elements in <People>
For Each Element As Xml.XmlElement In ElementList
'gets the S7-JEHILL value from the tag name
PersonName = Element.ChildNodes(0).Name
'gets the 20:47 from the tag value i.e. inner XML
OutTime = Element.ChildNodes(0).ChildNodes(0).InnerXml
Console.WriteLine(String.Format("{0} {1}", PersonName, OutTime))
Next
Console.ReadKey()
End Sub

XML elements source contains spaces

I'm very new in reading XML content and now i'm running into the issue that some XML elements are containing a white space and VB.net is not accepting this.
Please have a look at the line of code starting with "Today_CurrentTemp". In this line you find an element , the space and quotes are not accepted like this by the XDocument.
Please help me how to work arround this. I cannot change the XML source format.
Const URL As String = "http://xml.buienradar.nl/"
Try
Dim xml = XDocument.Load(URL)
Today_DescriptionShort = xml.<buienradarnl>.<weergegevens>.<verwachting_vandaag>.<samenvatting>.Value
Today_DescriptionLong = xml.<buienradarnl>.<weergegevens>.<verwachting_vandaag>.<tekst>.Value
Today_CurrentTemp = xml.<buienradarnl>.<weergegevens>.<actueel_weer>.<weerstations>.<weerstation id="6391">.<temperatuurGC>.Value
The element <weerstation id="6391"> does not contain whitespace in its name.
The whitespace indicates that the next literal is considered as an Xml Attribute with a specific value in double quotes (id="6391").
Here is how you get the current temp:
Today_CurrentTemp = xml.<buienradarnl>.<weergegevens>.<actueel_weer>.<weerstations>.<weerstation>.Where(Function (x) x.Attribute("id") = "6391").First().<temperatuurGC>.Value
I used a lambda expression to give me the first occurance of an element named <weerstation> with an Attribute named id and value 6391.
I assume that the id is unqiue so the .First() appraoch is correct.
That works perfectly!
Now I have a similar issue with the line
<icoonactueel zin="bewolkt" ID="p">http://xml.buienradar.nl/icons/p.gif</icoonactueel>
<temperatuur10cm>11.3</temperatuur10cm>
Where bewolkt can have different values and the ID changes as wel, based on the type of weather. The only that I would like to have out of this element is the URL.
How to handle this?
see part of the XML below as example:
<weerstation id="6391">
<stationcode>6391</stationcode>
<stationnaam regio="Venlo">Meetstation Arcen</stationnaam>
<lat>51.30</lat>
<lon>6.12</lon>
<datum>04/13/2016 11:50:00</datum>
<luchtvochtigheid>83</luchtvochtigheid>
<temperatuurGC>10.5</temperatuurGC>
<windsnelheidMS>2.12</windsnelheidMS>
<windsnelheidBF>2</windsnelheidBF>
<windrichtingGR>123.0</windrichtingGR>
<windrichting>OZO</windrichting>
<luchtdruk>-</luchtdruk>
<zichtmeters>-</zichtmeters>
<windstotenMS>3.7</windstotenMS>
<regenMMPU>-</regenMMPU>
<icoonactueel zin="bewolkt" ID="p">http://xml.buienradar.nl/icons/p.gif</icoonactueel>
<temperatuur10cm>11.3</temperatuur10cm>
Try this...
Const URL As String = "http://xml.buienradar.nl/"
Sub Main()
Dim Today_DescriptionShort
Dim Today_DescriptionLong
Dim Today_CurrentTemp
Try
Dim xsrcdoc = XDocument.Load(URL)
Today_DescriptionShort = (From xml In xsrcdoc.Descendants("verwachting_vandaag")
Select New With {.Val = xml.Element("samenvatting").Value}).FirstOrDefault
Today_DescriptionLong = (From xml In xsrcdoc.Descendants("verwachting_vandaag")
Select New With {.Val = xml.Element("tekst").Value}).FirstOrDefault
Today_CurrentTemp = (From xml In xsrcdoc.Descendants("weerstation").Where(Function(x) x.Attribute("id").Value = "6391")
Select New With {.Val = xml.Element("temperatuurGC").Value}).FirstOrDefault
Catch ex As Exception
End Try
End Sub

Splitting string in VB.NET produces unusual results

I am using the Split function in VB.NET, and it is producing a weird result when I display the output.
I have an XML document, and I just want to loop through each <backup> tag in the document, so I am using:
Dim XMLString As String
XMLString = "<backup>INFO</backup><backup>ANOTHER INFO</backup>"
Dim SplitBackup As String()
SplitBackup = XMLString.Split("<backup>")
For Each BackupContent In SplitBackup
MsgBox(BackupContent)
Next
Now, one would expect this to output INFO in a MsgBox, I click OK and then another one would popup and show 'ANOTHER INFO', but it seems that the Split function is getting stuffed up with the '<' and '>' in it. Is there someway I can get around this by escaping it, or parsing it some other way.
Any suggestions are much appreciated!
Give XML a chance.
Dim bups As XElement = <backups><backup>INFO</backup><backup>ANOTHER INFO</backup></backups>
For Each xe As XElement In bups.Elements
Debug.WriteLine(xe.Value)
Next
One possibility to do this is to use regular expression to split the tags (and escape the problematic symbols) and then use LINQ to Objects to get the value from each tag:
Dim XMLString As String = "<backup>INFO</backup><backup>ANOTHER INFO</backup>"
Dim words = Regex.Split(XmlString, "\<backup\>").Where(function(f) not String.IsNullOrEmpty(f)).Select(function(f) f.Replace("</backup>", String.Empty)) '
for each word in words
Console.WriteLine(word)
next word
The output is:
INFO
ANOTHER INFO
What the code does:
Dim words = Regex
' split on every tag
.Split(XmlString, "\<backup\>")
' remove empty items
.Where(function(f) not String.IsNullOrEmpty(f))
' remove trailing closing tag and thus retrieve the value within
.Select(function(f) f.Replace("</backup>", String.Empty))
As already suggested you better learn how to use the build-in XML support - it is easier and safer because you do not need to pay attention to the brackets - < and > are automatically handled. A possible solution could look like this (! you need to have a valid XML structure - one unique root node!):
' !!! you need to have a valid XML element - one root node !!!
Dim XMLString As String = "<root><backup>INFO</backup><backup>ANOTHER INFO</backup></root>"
dim words = XDocument.Parse(XMLString).Root.Descendants("backup").Select(function (f) f.Value)
for each word in words
Console.WriteLine(word)
next word
The output is the same as above. How does the code work:
dim words = XDocument
' parse the specified XML structure; use Load("file.xml") to load from file
.Parse(XMLString)
' from the root node
.Root
' take all nodes matching the specified tag
' note - no need to pay attention to the < and >
.Descendants("backup")
' select the value of the XML node
.Select(function (f) f.Value)
You would need to get rid of the close element.
So you could use:
Dim XMLString As String
XMLString = "<backup>INFO</backup><backup>ANOTHER INFO</backup>"
Dim SplitBackup As String()
SplitBackup = XMLString.Split("<backup>")
For Each BackupContent In SplitBackup
Dim Something() as string
Something = BackupContent.Split("</backup">)
MsgBox(Something(0))
Next
Not the most elegant coding though.