VB - Issue using XPath reading an XML - vb.net

I am currently trying to read in an XML node from a filepath which I pass to my method.
Public Function ReadXMLForIsite(xmlFileName As String)
Dim IsitePath As String
Dim doc As New XPathDocument(xmlFileName)
Dim nav As XPathNavigator
Dim iter As XPathNodeIterator
nav = doc.CreateNavigator
iter = nav.Select("GovTalkMessage/Header") 'Node name
'Loop through the records in that node
While iter.MoveNext
Dim lstNav As XPathNavigator
'Get the data we need from the node
Dim iterNews As XPathNodeIterator
lstNav = iter.Current
iterNews = lstNav.SelectDescendants(XPathNodeType.Element, False)
'Loop through the child nodes
While iterNews.MoveNext
Debug.WriteLine(iterNews.Current.Name & ": " & iterNews.Current.Value)
End While
End While
Return IsitePath
End Function
Every time i run this method (even with different node names) the variable 'iter' states that 'debugger display proxy is a type and cannot be used as an expression'. This occurs just before the while statement, therefore does not go in. Any help would be much appreciated. Thanks!

Try to load your Xml into an XDocument.
Dim xdoc As XDocument = XDocument.Load("X:\Jacob.Freeman\RTI\TestXML\0001R.xml")
Dim headerNode = xdoc.Descendants.First(Function(x) x.Name.LocalName = "Header")
For Each desc In headerNode.Descendants()
Console.WriteLine(desc.Name.LocalName + ":" + desc.Value)
Next
Console.ReadLine()

Related

Adding multiple strings to a listbox from text

I have a text file I need to get multiple strings from, I can sort of do it but it only shows the first string in the listbox
When we tried with XML reader it was collecting everything in the XML that was tagged Object Identifier along with the cameras
I need to look for lines similar to the following, there could be any amount
Object Identifier="./Cameras/MyCamera" Label="Standard Camera" Name="MyCamera" Type="Camera"
key identifiers:
./Cameras/
Label="Standard Camera"
Type="Camera"
I could use "MyCamera" after ./Cameras/ or Name="MyCamera" both of these are common in each occurrence of the lines
in my example below it has the file I wish to read it should list 3 cameras
https://www.dropbox.com/s/dy7r2auf9vv0m7g/testvb.zip
The XML is generated by Thea render, its the scene file with the model, lights etc taken out so it just leaves cameras and some core settings
Thanks to varocarbas, this is the code that solves my problem:
Dim path As String = "C:\Users\jen\Desktop\test\temp.xml"
Dim settings As System.Xml.XmlReaderSettings = New System.Xml.XmlReaderSettings()
settings.ConformanceLevel = System.Xml.ConformanceLevel.Fragment
Using reader As System.Xml.XmlReader = System.Xml.XmlReader.Create(path)
While (reader.Read())
If (reader.NodeType = System.Xml.XmlNodeType.Element) Then
If (reader.Name = "Object") Then
'Object Identifier="./Cameras/MyCamera" Label="Standard Camera" Name="MyCamera" Type="Camera"
Dim Identifier As String = reader.GetAttribute("Identifier") '"./Cameras/MyCamera"
Dim Label As String = reader.GetAttribute("Label") '"Standard Camera"
Dim Name As String = reader.GetAttribute("Name") '"MyCamera"
Dim Type As String = reader.GetAttribute("Type") '"Camera"
Dim wholeString As String = Name 'WHOLE STRING TO BE ADDED TO THE LISTBOX
'Adding the string to ListBox1
If (wholeString.Trim.Length > 0) And Type = "Camera" Then
ListBox1.Items.Add(wholeString)
End If
End If
End If
End While
End Using
You can use the XMLReader I proposed in another answer and do the following modifications on it:
Dim path As String = "temp.txt"
Dim settings As System.Xml.XmlReaderSettings = New System.Xml.XmlReaderSettings()
settings.ConformanceLevel = System.Xml.ConformanceLevel.Fragment
Using reader As System.Xml.XmlReader = System.Xml.XmlReader.Create(path)
While (reader.Read())
If (reader.NodeType = System.Xml.XmlNodeType.Element) Then
If (reader.Name = "Object") Then
'Object Identifier="./Cameras/MyCamera" Label="Standard Camera" Name="MyCamera" Type="Camera"
Dim Identifier As String = reader.GetAttribute("Identifier") '"./Cameras/MyCamera"
Dim Label As String = reader.GetAttribute("Label") '"Standard Camera"
Dim Name As String = reader.GetAttribute("Name") '"MyCamera"
Dim Type As String = reader.GetAttribute("Type") '"Camera"
Dim wholeString As String = Identifier & " - " & Label & " - " & Name & " - " & Type 'WHOLE STRING TO BE ADDED TO THE LISTBOX
'Adding the string to ListBox1
If (wholeString.Trim.Length > 0) Then
ListBox1.Items.Add(wholeString)
End If
End If
End If
End While
End Using
This code retrieves all the information you want and stores it in LisBox1 by putting " - " to separate each element. This is information more than enough and you should be the one performing any further change, for example: converting "./Cameras/MyCamera" into "./Cameras/" (there is an indication of how to do that in my previous code); or change the way the different items are displayed in the listBox (or perhaps you want to include one listBox per element: one for identifiers, another for labels, etc.).

CovrageInfo.CreateFromFile is giving an error

I have replicated the code from the example to collect the result for code coverage from Here except that my code is vb.net
Here is my code
Imports Microsoft.VisualStudio.Coverage.Analysis
Module Module1
Sub Main()
Using info As CoverageInfo = CoverageInfo.CreateFromFile("C:MyFile\data.coverage")
Dim lines As New List(Of BlockLineRange)()
For Each [module] As ICoverageModule In info.Modules
Dim coverageBuffer As Byte() = [module].GetCoverageBuffer(Nothing)
Using reader As ISymbolReader = [module].Symbols.CreateReader()
Dim methodId As UInteger = 0
Dim MethodName As String = ""
Dim undecoratedMethodName As String = ""
Dim ClassName As String = ""
Dim NameSpaceName As String = ""
lines.Clear()
While reader.GetNextMethod(methodId, MethodName, undecoratedMethodName, ClassName, NameSpaceName, lines)
Dim stats As CoverageStatistics = CoverageInfo.GetMethodStatistics(coverageBuffer, lines)
Console.WriteLine("Method {0}{1}{2}{3}{4} has:" & NameSpaceName & ClassName & undecoratedMethodName)
Console.WriteLine(" blocks covered are {0}", stats.BlocksCovered)
End While
End Using
Next
End Using
End Sub
End Module
When I run this on the line for CreateFromFile i get a ImageNotFoundException
Image File "C:\SomeAddress\MyServer\UnitTest.dll" could not be found
I have already as per instructions added the neccessary dlls to my project copied and the other 2 as references.
And yet another tumbleweed moment....
Basically the problem was that folder containing my coverage file also had to contains all the dlls used within that assembely that tests were ran on in order to create that object.
hope this helps you if you ever stumbled over this issuen :)

HtmlAgilityPack : How do I combine html elements together into one tag with a class?

Issue:
I need to examine some HTML elements using HtmlAgilityPack and combine the tag names.
Is it possible to extract each tag, from the parent to the child, replacing it with a span that has a class with a name of “strikeUEmStrong”. Also, the name changes based on the HTML element.
Order of the name of the class does in fact matter, I realized this through trial and error. As long as its able to get all of the elements and combine them together. It is very possible that it will have multiple text nodes with various levels of formatting.
This will affect multiple paragraphs.
For example, if I have this html code:
<p>
<strike><u><em><strong>four styles</strong></em></u></strike></p>
How do I convert it to this:
<p>
<span class="strikeUEmStrong">four styles</span></p>
Its possible to have this type of code as well:
<p>
<strike><u><em><strong>four styles</strong></em></u></strike> <strike><u><em>three styles</em></u></strike></p>
<p>
<em><strong>two styles</strong></em></p>
The output should look like this:
<p>
<span class="strikeUEmStrong">four styles</span> <span class="strikeUEm">three styles<span></p><p><span class="emStrong">two styles<span></p>
Prototype:
'Retrive the class name of each format node
Function GetClassName(ByVal n As HtmlNode) As String
Dim ret As String = String.Empty
If (n.Name <> "#text") And (n.Name <> "p") Then
ret = n.Name + " "
End If
'Get the next node
For Each child As HtmlNode In n.ChildNodes
ret &= GetClassName(child)
Next
Return ret
End Function
'Create a list of class names
Function GetClassNameList(ByVal classNameList As String) As List(Of String)
Dim ret As New List(Of String)
Dim classArr() As String = classNameList.Split(" ")
For Each className As String In classArr
ret.Add(className)
Next
Return ret
End Function
'Sort a list of class names and return a merged class string
Function GetSortedClassNameString(ByVal classList As List(Of String)) As String
Dim sortedMergedClass As String = String.Empty
classList.Sort()
For Each className As String In classList
sortedMergedClass &= className
Next
Return sortedMergedClass
End Function
'Lets point to the body node
Dim bodyNode As HtmlNode = htmlDoc.DocumentNode.SelectSingleNode("//body")
'Lets create some generic nodes
Dim currPNode As HtmlNode
Dim formatNodes As HtmlNodeCollection
Dim text As String = String.Empty
Dim textSize As Integer = 0
'Make sure the editor has something in it
If editorText <> "" Then
'Send the text from the editor to the body node
If bodyNode IsNot Nothing Then
bodyNode.InnerHtml = editorText
End If
Dim pNode = bodyNode.SelectNodes("//p")
Dim span As HtmlNode = htmlDoc.CreateElement("span")
Dim tmpBody As HtmlNode = htmlDoc.CreateElement("body")
Dim textNode As HtmlNode = htmlDoc.CreateTextNode
Dim pCount As Integer = bodyNode.SelectNodes("//body/p").Count - 1
For childCountP As Integer = 0 To pCount
Dim paragraph = HtmlNode.CreateNode(htmlDoc.CreateElement("p").WriteTo)
'Which paragraph I am at.
currPNode = pNode.Item(childCountP)
'For this paragraph get me the collection of html nodes
formatNodes = currPNode.ChildNodes
'Count how many Format nodes we have in a paragraph
Dim formatCount As Integer = currPNode.ChildNodes.Count - 1
'Go through each node and examine the elements.
'Then look at the markup to create classes and then group them under one span
For child As Integer = 0 To formatCount
'Iterate through the formateNodes, strike, em, strong, etc.
Dim currFormatNode = HtmlNode.CreateNode(formatNodes(child).WriteTo)
'TODO: Handle nested images and links? How do we know what to rip out?
'First check for format nodes
'Note, we can't let it use everything because it will change nested elements as well. I.E. span within span.
If (currFormatNode.Name <> "#text") And (currFormatNode.Name = "strike") Or (currFormatNode.Name = "em") _
Or (currFormatNode.Name = "strong") Or (currFormatNode.Name = "u") Or (currFormatNode.Name = "sub") _
Or (currFormatNode.Name = "sup") Or (currFormatNode.Name = "b") Then
'strip all tags, just take the inner text
span.InnerHtml = currFormatNode.InnerText
'Create a text node with text from the lowest node
textNode = htmlDoc.CreateTextNode(span.InnerText)
'Recursively go through the format nodes
'Create a list from the string
'Then sort the list and return a string
'Appending the class to the span
span.SetAttributeValue("class", GetSortedClassNameString(GetClassNameList(GetClassName(currFormatNode).Trim())))
'Attach the span before the current format node
currFormatNode.ParentNode.InsertBefore(span, currFormatNode)
'Remove the formatted children leaving the above node
currFormatNode.ParentNode.ChildNodes.Remove(currFormatNode)
'We need to build a paragraph here
paragraph.InnerHtml &= span.OuterHtml
'Lets output something for debugging
childNodesTxt.InnerText &= span.OuterHtml
Else 'handle #text and other nodes seperately
'We need to build a paragraph here
paragraph.InnerHtml &= span.OuterHtml
textNode = htmlDoc.CreateTextNode(currFormatNode.InnerHtml)
'Lets output something for debugging
childNodesTxt.InnerText &= textNode.OuterHtml
End If
Next
'End of formats
'Start adding the new paragraph's to the body node
tmpBody.AppendChild(paragraph)
Next
'End of paragraphs
'Clean out body first and replace with new elements
htmlDoc.DocumentNode.SelectSingleNode("//body").Remove()
'Update our body
htmlDoc.DocumentNode.SelectSingleNode("//html").AppendChild(tmpBody)
End If
htmlDoc.Save(Server.MapPath("html\editor.html"))
End If
Output:
<span class="strikeuemstrong">four styles</span>
Finally getting the right output, after I fixed the ordering issue. Thank you for the help.
This is not a straight forward question to answer. I'll describe how I'd write the algorithm to do this, and include some pseudo code to help.
I'd get my parent tag. I'll assume you want to do this for all "p" tags
I'd iterate over my children tags, taking the tag name and appending it into a class name
I'd recursively iterate children until I get my appended tag name
Pseudo-code. Please excuse any typos, as I'm typing this on the fly.
public string GetClassName(Node n)
{
var ret = n.TagName;
foreach(var child in n.ChildNodes)
{
ret += GetClassName(child);
}
return ret;
}
foreach(var p in paragraphs)
{
foreach(var child in p.ChildNodes)
{
var span = new Span();
span.InnerText = child.InnerText; // strip all tags, just take the inner text
span.ClassName = GetClassName(child);
child.ReplaceWith(span); // note: if you do this with a FOREACH and not a for loop, it'll blow up C# for modifying the collection while iterating. Use for loops. if you're going to do "active" replacement like in this pseudo code
}
}
I'd be happy to modify my answer once I get more context. Please review what I'm suggesting and comment on it with more context if you need me to refine my suggestion. If not, I hope this gets you what you need :)

VB.net Object Array throwing an exception

I am getting an exception when running the following code.
Public Function getSongs() As Song()
' Dim dir As New DirectoryInfo(Application.ExecutablePath)
Dim dir As New DirectoryInfo(directory)
Dim songsInDir() As Song = Nothing
Dim i As Integer = 0
For Each file As FileInfo In dir.GetFiles()
'only read ".mp3" files
If file.Extension = ".mp3" Then
songsInDir(i) = New Song(file.Name)
i = +i
End If
Next
Return songsInDir
End Function
I get an error on line:
songsInDir(i) = New Song(file.Name)
I get an uncaught exception that says:
"Object reference not set to an instance of an object."
The song object has a:
Public Sub new(By Val filename as String)
... sub that sets a variable and retrieves file info (this code works)
Any help would be appreciated!
Try using a list:
Public Function getSongs() As Song()
Dim dir As New DirectoryInfo(directory)
Dim songsInDir() As New List(of Song)
For Each file As FileInfo In dir.GetFiles()
'only read ".mp3" files
If file.Extension = ".mp3" Then
songsInDir.Add(New Song(file.Name)
End If
Next
Return songsInDir.ToArray()
End Function
Your problem is that arrays need a size when they're initialized and setting it to Nothing gives you exactly that. Give the array a size and don't set it to Nothing. Also, there's a much cleaner way to do this.
Public Function getSongs() As Song()
Dim songFiles As String() = Directory.GetFiles(directory, "*.mp3")
Dim songsInDir(songFiles.Length) As Song
Dim i As Integer = 0
For Each file As String In songFiles
songsInDir(i) = New Song(Path.GetFileName(file))
i = +i
Next
Return songsInDir
End Function
You should specify the array size
Dim i as Integer = dir.GetFiles().count or dir.FilesCount()
Dim songsInDir(i) As Song = Nothing
or you can use dynamic array
put this line inside your for loop
ReDim Preserve songsInDir(i)

VBA - grabbing column names from lotus notes database using getColumnNames method

So I have a view (object name is 'view') in a Lotus Domino db from which I want to grab the column names and put them in an array:
Dim view As Domino.NotesView
Set view = db.GetView(viewScen)
//viewScen is a string containing the actual view's name
//db is a string containing the actual db name
These declarations work fine, but when I try to assign those values to an array using the method called 'getColumnNames', the VBA editor tells me that the method is not supported for that object:
Dim someArray() As String
//I tried both of the following with no sucess...
someArray = view.getColumnNames
someArray() = view.getColumnNames
What am I doing wrong?
I think you can do a For..Each with columns
dim idx as integer
dim OneCol as Column
redim someArray(view.Columns.Count)
For idx = 0 to view.Columns.Count - 1
someArray(idx) = view.Columns(idx).name
Next
According to the 8.0 help files, the getColumnNames method is not supported in COM/OLE. However, the attribute ColumnNames is supported. This is VB code from the Help file:
Private Sub ViewColumnNames_Click()
Dim s As New NotesSession
s.Initialize
Dim dir As NotesDbDirectory
Dim db As NotesDatabase
Dim v As NotesView
Dim cns As String
Set dir = s.GetDbDirectory("")
Set db = dir.OpenDatabase("Web test")
Set v = db.GetView("Main View")
For Each cn In v.ColumnNames
cns = cns + cn + Chr(10)
Next
MsgBox cns, , "Columns in Main View"
End Sub