Click here to Skip to main content
15,891,473 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
After creating a XmlDocument object and creating XML, I can use the .SelectNodes method to get back the nodes from the original object by not prefixing the node names with the namespace prefix. I get nothing if I use the prefix. However when I save the XML document, and reload it. I get the reverse effect. Not using the prefix returns nothing while using the prefix gets results. Can anyone help me understanding here and suggest the correct way.

I have attached some test code here in VB;
Dim Root As XmlElement = Xdoc.DocumentElement
 Dim xmldecl As XmlDeclaration
 xmldecl = Xdoc.CreateXmlDeclaration("1.0", "UTF-8", Nothing)
 Xdoc.InsertBefore(xmldecl, Root)

 Dim BooksNode As XmlNode
 BooksNode = Xdoc.CreateNode(XmlNodeType.Element, "Books", "")
 Dim Attrib As XmlAttribute = Xdoc.CreateAttribute("xmlns")
 Attrib.Value = "http://www.Company.com.au/xml"
 BooksNode.Attributes.Append(Attrib)
 Xdoc.AppendChild(BooksNode)

 Dim BookNode As XmlNode
 BookNode = Xdoc.CreateNode(XmlNodeType.Element, "Book", "")
 BookNode.InnerText = ""
 BooksNode.AppendChild(BookNode)

 Dim BookNameNode As XmlNode
 BookNameNode = Xdoc.CreateNode(XmlNodeType.Element, "BookName", "")
 BookNameNode.InnerText = "Hitchhikers guide to the galaxy"
 BookNode.AppendChild(BookNameNode)

 Dim BookNode2 As XmlNode
 BookNode2 = Xdoc.CreateNode(XmlNodeType.Element, "Book", "")
 BookNode2.InnerText = ""
 BooksNode.AppendChild(BookNode2)

 Dim BookNameNode2 As XmlNode
 BookNameNode2 = Xdoc.CreateNode(XmlNodeType.Element, "BookName", "")
 BookNameNode2.InnerText = "The Power of one"
 BookNode2.AppendChild(BookNameNode2)

 Dim NsMgr As New XmlNamespaceManager(Xdoc.NameTable)
 NsMgr.AddNamespace("bk", "http://www.Company.com.au/xml")

 Dim BooksNoNsPrefix = Xdoc.SelectNodes("/Books/Book", NsMgr)
 Debug.Print("No Namespace prefix:" & BooksNoNsPrefix.Count.ToString)

 Dim BooksNsPrefix = Xdoc.SelectNodes("/bk:Books/bk:Book", NsMgr)
 Debug.Print("Using Namespace prefix:" & BooksNsPrefix.Count.ToString)

 Xdoc.Save("C:\Temp\Test.xml")
 Dim NewXdox As New XmlDocument
 NewXdox.Load("C:\Temp\Test.xml")

 Dim NsMgr2 As New XmlNamespaceManager(NewXdox.NameTable)
 NsMgr2.AddNamespace("bk", "http://www.Company.com.au/xml")

 Dim BooksNoNs2 = NewXdox.SelectNodes("/Books/Book", NsMgr2)
 Debug.Print("No Namespace prefix:" & BooksNoNs2.Count.ToString)

 Dim BooksNs2 = NewXdox.SelectNodes("/bk:Books/bk:Book", NsMgr2)
 Debug.Print("Using Namespace prefix:" & BooksNs2.Count.ToString)

The Output is;
No Namespace prefix : 2
Using Namespace prefix : 0
No Namespace prefix : 0
Using Namespace prefix : 2
Posted
Comments
PIEBALDconsult 29-Oct-13 0:35am    
XML namespaces are rather tricky and I've had a bit of trouble working with them.
One thing I would cauthion is not to use the default (empty) namespace.
It looks like what you have should work. Can you add a snippet of the generated XML?

Come to think of it, I suppose the Attribute you create doesn't get interpreted as a namespace until it's read in -- that could be the issue, but I don't know the solution.
Coding123456 12-Nov-13 20:11pm    
Thanks for your reply PEIBALDconsult, You were on the right track.

1 solution

It's because you're not adding your namespace as you should. Rather than add it as an attribute after you create a node, add it as the namespace when you create the node:
VB
Dim xdoc As New XmlDocument
Dim Root As XmlElement = Xdoc.DocumentElement
Dim xmldecl As XmlDeclaration
xmldecl = xdoc.CreateXmlDeclaration("1.0", "UTF-8", Nothing)
Xdoc.InsertBefore(xmldecl, Root)

Dim BooksNode As XmlNode
Dim ns As String = "http://www.Company.com.au/xml"
BooksNode = xdoc.CreateNode(XmlNodeType.Element, "Books", ns)
xdoc.AppendChild(BooksNode)

Dim BookNode As XmlNode
BookNode = xdoc.CreateNode(XmlNodeType.Element, "Book", ns)
BookNode.InnerText = ""
BooksNode.AppendChild(BookNode)

Dim BookNameNode As XmlNode
BookNameNode = xdoc.CreateNode(XmlNodeType.Element, "BookName", ns)
BookNameNode.InnerText = "Hitchhikers guide to the galaxy"
BookNode.AppendChild(BookNameNode)

Dim BookNode2 As XmlNode
BookNode2 = xdoc.CreateNode(XmlNodeType.Element, "Book", ns)
BookNode2.InnerText = ""
BooksNode.AppendChild(BookNode2)

Dim BookNameNode2 As XmlNode
BookNameNode2 = xdoc.CreateNode(XmlNodeType.Element, "BookName", ns)
BookNameNode2.InnerText = "The Power of one"
BookNode2.AppendChild(BookNameNode2)

Dim NsMgr As New XmlNamespaceManager(xdoc.NameTable)
NsMgr.AddNamespace("bk", "http://www.Company.com.au/xml")
NsMgr.PushScope()

Dim BooksNoNsPrefix = Xdoc.SelectNodes("/Books/Book", NsMgr)
Debug.Print("No Namespace prefix:" & BooksNoNsPrefix.Count.ToString)

Dim BooksNsPrefix = Xdoc.SelectNodes("/bk:Books/bk:Book", NsMgr)
Debug.Print("Using Namespace prefix:" & BooksNsPrefix.Count.ToString)

Xdoc.Save("C:\Temp\Test.xml")
Dim NewXdox As New XmlDocument
NewXdox.Load("C:\Temp\Test.xml")

Dim NsMgr2 As New XmlNamespaceManager(NewXdox.NameTable)
NsMgr2.AddNamespace("bk", "http://www.Company.com.au/xml")

Dim BooksNoNs2 = NewXdox.SelectNodes("/Books/Book", NsMgr2)
Debug.Print("No Namespace prefix:" & BooksNoNs2.Count.ToString)

Dim BooksNs2 = NewXdox.SelectNodes("/bk:Books/bk:Book", NsMgr2)
Debug.Print("Using Namespace prefix:" & BooksNs2.Count.ToString)
 
Share this answer
 
Comments
Coding123456 12-Nov-13 19:55pm    
Thanks woopsydoozy. That fixed it. I guess I have come to rely on the compiler a bit too much when checking for errors.
So this means that I always need to provide the namespace prefix '/bk:Books/bk:Book' in the xpath string when selecting the node. Even though I have specified a namespace 'NewXdox.SelectNodes("/bk:Books/bk:Book", NsMgr2)'. Is this normal practice? Or is there a way to get back the data using the un-prefixed xpath string '/Books/Book', just to make it look simpler and shorter for longer paths?
woopsydoozy 13-Nov-13 10:43am    
Yes, this is the normal practice. If you don't specify the prefix, then it doesn't know to use the namespace you've defined. Note that you can define your prefix as anything you want, though, so you can make it a single character, if that helps. For processing any XML with a namespace, you can remove the namespace attributes and reload it into your object, then you don't need to worry about namespaces anymore. But I don't recommend that--namespaces aren't that bothersome once you've worked with them a little.
Coding123456 13-Nov-13 16:44pm    
Thanks, you have cleared ii up well.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900