Question Inserting data into xml node

evilbird2001

New member
Joined
Dec 20, 2012
Messages
3
Programming Experience
1-3
Im just recently getting back into programming vb after being away for many years. Im currently working on a project that requires i insert or append data to a specific node in an xml file.

When i run this bit of code.

Dim XMLDom As New XmlDocument()
XMLDom.Load("C:\Users\PatDaRat\Dropbox\WindowsApplication18\test.xml")
Dim newXMLNode As XmlNode = XMLDom.SelectSingleNode("rule")
Dim childNode As XmlNode = XMLDom.CreateNode(XmlNodeType.Element, "one-of", "")
Dim newAttribute As XmlAttribute = XMLDom.CreateAttribute("item3", TextBox1.Text, "")
childNode.Attributes.Append(newAttribute)
newXMLNode.AppendChild(childNode)

I get this error with line 7 highlighted.

"An unhandled exception of type 'System.NullReferenceException' occurred in WindowsApplication18.exe


Additional information: Object reference not set to an instance of an object."

I've been searching for quite awhile and staring this seeming simply piece of code down, and i simply cant come to a conclusion as to why im getting this error.
I would greatly appreciate an advice anyone might have to offer.

Thanks in advance for your help!
 

IanRyder

Well-known member
Joined
Sep 9, 2012
Messages
1,130
Location
Healing, NE Lincs, UK
Programming Experience
10+
Hi,

In this case it means that the node "rule" does not exist in the root location of the XML file. To demonstrate, consider this simple XML file:-

HTML:
<?xml version="1.0" encoding="utf-8"?>
<bookstore>
  <book>
    <title>The Lord Of The Rings</title>
    <title>Planet of the Apes</title>
    <title>The Thing</title>
  </book>
</bookstore>
If you were to use Dim newXMLNode As XmlNode = XMLDom.SelectSingleNode("title") to select the first "title" node this would give a NullReferenceException when you come to use this since the "title" node does not exist in the root location of the XML file. To get the first "title" node you would need to use:-

Code:
Dim newXMLNode As XmlNode = XMLDom.SelectSingleNode("//bookstore/book/title")
Hope that helps.

Cheers,

Ian
 
Last edited:

evilbird2001

New member
Joined
Dec 20, 2012
Messages
3
Programming Experience
1-3
Here is my xml file. I tried doing as you suggested and used //grammar/rule, but this results in the same error. I even tried to just select the grammar node with the same result. Seems as though no matter what node i attempt selecting i get newXMLNode is Nothing. Maybe this is a nonstandard formatted xml file?

HTML:
<grammar version="1.0" xml:lang="en-US" root="rootRule" xmlns="http://www.w3.org/2001/06/grammar">
  <rule id="rootRule">
    <one-of>
      <item>Hello</item>
      <item>What time is it</item>
      <item>What is today</item>
      <item>Close application</item>
      <item>How are you</item>
    </one-of>
  </rule>
</grammar>

Thanks again for your help.
 
Last edited by a moderator:

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,334
Location
Norway
Programming Experience
10+
It is a standard xml file with a namespace. XmlNamespaceManager class can help you deal with that. Here's an example setting up that:
        Dim ns As New XmlNamespaceManager(XMLDom.NameTable)
        ns.AddNamespace("def", XMLDom.DocumentElement.NamespaceURI) 'def prefix
        ns.AddNamespace(String.Empty, XMLDom.DocumentElement.NamespaceURI) 'default namespace

Then you can refer to the node (names) qualified by namespace using the namespace prefix:
Dim rule = XMLDom.SelectSingleNode("//def:grammar/def:rule", ns)

Note that // in XPath expression means a relative path, it will match a node anywhere in document tree that matches the specified path.

When adding elements that you want to place in same namespace you must specify the namespace uri when creating them:
        Dim oneof = XMLDom.CreateElement("one-of", ns.DefaultNamespace)
        Dim item = XMLDom.CreateElement("item", ns.DefaultNamespace)
        item.InnerText = TextBox1.Text        
        oneof.AppendChild(item)
        rule.AppendChild(oneof)

Strangly that should not be done when creating attributes:
        Dim newAttribute = XMLDom.CreateAttribute("repeat")
        newAttribute.Value = "0-1"
        oneof.Attributes.Append(newAttribute)

[hr][/hr]
I will also show the code using System.Xml.Linq namespace tools, because it usually is much easier to work with than the old System.Xml tools.
The way to use a default namespace here is the Imports statement, this is used by the xml literals lookup in last line of the following code example.
Imports <xmlns="http://www.w3.org/2001/06/grammar">

When creating new elements using xml literals seems to cause the namespace definition to be repeated, so this example creates XElements with specified namespace:
        Dim doc = XDocument.Load("test.xml")
        Dim nsroot = doc.Root.GetDefaultNamespace
        Dim item As New XElement(nsroot + "item", TextBox1.Text)
        Dim oneof As New XElement(nsroot + "one-of", item)
        oneof.Add(New XAttribute("repeat", "0-1"))
        doc.<grammar>.<rule>.First.Add(oneof)
 

IanRyder

Well-known member
Joined
Sep 9, 2012
Messages
1,130
Location
Healing, NE Lincs, UK
Programming Experience
10+
JohnH beat me to this post and is way more knowledgeable than I am but I have learnt a few things today so thought I would still post anyway so see if it helps further.

Cheers,

Ian.

I am still relatively new to XML files and after looking at your question I have learnt a few things today.

I finally narrowed down the issue to your problem being the fact that you have declared an XML NameSpace attribute in your "grammer" node. (like I said, I am still relatively new to XML files and this has been a bit of learning curve for me today but every day is a good day to learn)

The offending attribute is this one:-

HTML:
xmlns="http://www.w3.org/2001/06/grammar"
I could provide loads of links on the net to where I finally got my understanding but to summarise all my learning today you have two options:-

Option 1
You can change the XML file you are using to include a "NAME" for the NameSpace you have declared. i.e:-

<grammar version="1.0" xml:lang="en-US" root="rootRule" xmlns:myNameSpace="http://www.w3.org/2001/06/grammar">

You then need to change your code to recognise and interact with this NameSpace before you can access the nodes within the NameSpace

Code:
'Define a Namespace Manager for the XML file
Dim NSmgr = New XmlNamespaceManager(XMLDom.NameTable)
'Add the NameSpace declared within the XML file
NSmgr.AddNamespace("myNameSpace", "http://www.w3.org/2001/06/grammar")
'Now when you select the nodes you must specify the NameSpace
'Manager where the node resides and leave the node selection statement as we had previously, being:-
Dim newXMLNode As XmlNode = XMLDom.SelectSingleNode("//grammar/rule", NSmgr)
'The rest that has been coded is the same
Option 2
You can leave your XML file as it is and declare a NameSpace within your project which you then need to reference with each node that you need to refer to. i.e_

Code:
'Define a Namespace Manager for the XML file
Dim NSmgr = New XmlNamespaceManager(XMLDom.NameTable)
'Add the NameSpace declared within the XML file and give it a name of
'you choosing
NSmgr.AddNamespace("myVBNameSpace", "http://www.w3.org/2001/06/grammar")
'Now when you select the nodes you must specify the NameSpace manager
'with the SelectSingleNode method as well as specifying the NameSpace name   
'within the string where the node resides, being:-
Dim newXMLNode As XmlNode = XMLDom.SelectSingleNode("//myVBNameSpace:grammar/myVBNameSpace:rule", NSmgr)
'The rest that has been coded is the same
I hope that explains things clearly enough, and experts, please do jump in if you can see any irregularities in my learning.
 
Top Bottom