0

I'm just starting out on one of my first programming projects in visual studio 2010.

I have an XML file that I have added into the program as an item. It has the following structure:

<lexeme><grapheme>Aalesund</grapheme>    <phoneme>'A:lI2s,Vnd</phoneme></lexeme>

There are 400,000 entries like that and what I would like to do is on a button press have a random lexeme selected from the xml file and then two labels populated with the corresponding grapheme and phoneme.

Could anyone point me in the right direction to begin with please? The tutorials I have found are for loading specific amounts of data, not just one random line and reference an external xml file location, not one that is internal to the project.

Thanks in advance.

Edit: I should say that I mean pseudo-random number. I was hoping to find a rand() function, but can't seem to?

Andy
  • 135
  • 2
  • 14
  • .Net [Random](http://msdn.microsoft.com/en-us/library/system.random.aspx) class on MSDN – psubsee2003 Feb 09 '13 at 20:09
  • If you look for `pseudo-random number in vb.net` in google search, the first result is this [Random Int in VB.Net](http://stackoverflow.com/questions/18676/random-int-in-vb-net). Have you checked that out? – Victor Zakharov Feb 09 '13 at 21:24

1 Answers1

1

There isn't a direct way of getting a random line from an XML. And relying on line number is dangerous because if the format of the XML were to be changed from:

<lexeme><grapheme>Aalesund</grapheme>    <phoneme>'A:lI2s,Vnd</phoneme></lexeme>

to:

<lexeme>
  <grapheme>Aalesund</grapheme>    
  <phoneme>'A:lI2s,Vnd</phoneme>
</lexeme>

Your randomly generated line number might not line up with a <lexeme> element anymore.

I think the best way to do it is to get all of the <lexeme> elements in a list and randomly generate a number that is within the range of the list:
(forgive me, but the code sample is in c#, I don't trust my VB.Net enough to write my code in VB)

var lexemeList = xDocument.Descendants("lexeme").ToList();
var random = new Random();

var randomLexeme = lexemeList[random.Next(0, lexemeList.Count-1)];

randomLexme will then have a pseudo-random <lexeme> element and you can parse it as you need to get the appropriate <grapheme> and <phoneme> elements.

If you do this though, keep in mind that the .net Random class is pseudo-random and uses the current timestamp as a seed. If you are going to be accessing objects regularly, it would be advisable to make the var random = new Random() variable as class-level field and create it once and just used the Next() method to get the next number, rather than creating a new Random() object whenever you need a random number.

Here's a more self contained function in VB.Net:

Dim rand = New Random()
Dim myXml = New XDocument()

Function GetRandomLexeme() as XElement

    Dim lexemeList = myXml.Descendants("lexeme").ToList()
    Dim randomLexeme = lexemeList(rand .Next(0, lexemeList.Count - 1))

    GetRandomLexeme = randomLexeme

End Function
psubsee2003
  • 8,563
  • 8
  • 61
  • 79
  • +1 for mentioning the fact there is no point in reading line # when working with XML files. – Victor Zakharov Feb 09 '13 at 21:22
  • Thank you psubsee. I have the xml file loaded in as an item in the solution explorer, but when I try and add the file as a new data source in the project there is no option to link it. – Andy Feb 10 '13 at 10:59
  • @Andy so you want to have your XML embedded in your application and load it when you start your application? – psubsee2003 Feb 10 '13 at 11:04
  • @Andy [here's a SO question](http://stackoverflow.com/q/8406749/250725) on loading an XML that is an embedded resource in your application. If you do it that way, then you will not be able to edit the XML file without recompiling your assembly. – psubsee2003 Feb 10 '13 at 11:09
  • @psubsee2003 since there are 400,000 entries, I would rather just read a lexeme when needed, but if that is too complicated then loading it on start up is fine. You are correct about it needing to be embedded. I have tried to follow this tutorial http://msdn.microsoft.com/en-us/library/ekw4dh3f(v=vs.100).aspx but as you see it's for an external xml file – Andy Feb 10 '13 at 11:09
  • @Andy take a look at the comment I made just before your last comment. Your question here is too complex to be made in just comments (and not really part of the question so it will be confusing if I add it to the answer). Using the `GetManifestResourceStream()` method will let you fetch the XML as a `Stream`, then you can load it into whatever object you want. I choose `XDocument` for my example because `LINQ` makes the query very simple. If you are using .Net4 or later, you can use `XDocument.Load(stream)` to parse the stream into an XDocument. – psubsee2003 Feb 10 '13 at 11:15
  • @Andy and [this question](http://stackoverflow.com/q/518935/250725) might help too, especially the comments on the accepted answer if you aren't sure how to build the XML as an embedded resource. – psubsee2003 Feb 10 '13 at 11:19
  • @psubsee2003 I have tried to add the folllowing: `Public Class Form1 Dim asm = Assembly.GetExecutingAssembly() Dim var = asm.GetManifestResourceStream("british-english-dictionary.xml") End Class` But I'm getting the error 'Assembly' is not declared. It may be inaccessible due to its protection level, despite the british-english-dictionary.xml being set to an Embedded Resource build action. – Andy Feb 10 '13 at 12:18
  • Did you add `using System.Reflection` to your code? [MSDN link for Assembly class](http://msdn.microsoft.com/en-us/library/system.reflection.assembly.aspx) – psubsee2003 Feb 10 '13 at 12:27
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/24265/discussion-between-andy-and-psubsee2003) – Andy Feb 10 '13 at 13:05