For starters, I will create an XML file that contains a Person node at the root and three nodes - Name that lies in the n1 namespace, Age that lies in the n2 namespace and Gender that is part of the default namespace.
A listing of the Sample.xml file
<?xml version="1.0" encoding="utf-8" ?>
<Person xmlns:n1="http://codeedifice.com/N1" xmlns:n2="http://codeedifice.com/N2" xmlns="http://codeedifice.com/N">
<n1:Name>Alvin</n1:Name>
<n2:Age>10</n2:Age>
<Gender>Male</Gender>
</Person>
The example that I am listing here lists the top three approaches taken by developers who are still getting their hands dirty with XML that contains namespaces. The next three approaches are alternatives that you must work out for yourself and pick the one that suits your actual requirement
Sub Main()
Dim xdoc As XmlDocument = New XmlDocument
xdoc.Load("Sample.xml")
'Fails due to lack of namespace
Console.WriteLine("Looking for Person Node(s) without a namespace manager...")
Dim xNodLst1 As Xml.XmlNodeList = xdoc.SelectNodes("/Person")
Console.WriteLine(Space(4) & "Found " & xNodLst1.Count & " matche(s)")
Dim nsMgr As XmlNamespaceManager = New XmlNamespaceManager(xdoc.NameTable)
nsMgr.AddNamespace("n1", "http://codeedifice.com/N1")
nsMgr.AddNamespace("n2", "http://codeedifice.com/N2")
'Fails since the namespaces do not include the default one
Console.WriteLine("Looking for Person Node(s) with the namespace manager not including the default namespace...")
Dim xNodLst2 As Xml.XmlNodeList = xdoc.SelectNodes("/Person", nsMgr)
Console.WriteLine(Space(4) & "Found " & xNodLst1.Count & " matche(s)")
nsMgr.AddNamespace("", "http://codeedifice.com/N")
'Fails since the empty string namespace is not useful (quite contrary to popular vote)
Console.WriteLine("Looking for Person Node(s) with the namespace manager including the default namespace as an empty string...")
Dim xNodLst3 As Xml.XmlNodeList = xdoc.SelectNodes("/Person", nsMgr)
Console.WriteLine(Space(4) & "Found " & xNodLst3.Count & " matche(s)")
nsMgr.RemoveNamespace("", "http://codeedifice.com/N") 'take the useless one out
nsMgr.AddNamespace("ALVIN", "http://codeedifice.com/N")
'Finally a working solution
Console.WriteLine("Looking for Person Node(s) with the namespace manager including the default namespace as a unique value - ALVIN...")
Dim xNodLst4 As Xml.XmlNodeList = xdoc.SelectNodes("/ALVIN:Person", nsMgr) 'Note how the dummy namespace is used
Console.WriteLine(Space(4) & "Found " & xNodLst4.Count & " matche(s)")
'A slightly more elegant solution that does not rely on the unique value ALVIN to be created by the developer
Console.WriteLine("Looking for Person Node(s) without the namespace manager using the localName XPath function...")
Dim xNodLst5 As Xml.XmlNodeList = xdoc.SelectNodes("/*[local-name()='Person']")
Console.WriteLine(Space(4) & "Found " & xNodLst5.Count & " matche(s)")
'Accessing the Name and Age nodes correctly will require the use of the namespace
Console.WriteLine("Looking for Name Node(s) with the namespace manager using the localName XPath function...")
Dim xNodLst6 As Xml.XmlNodeList = xdoc.SelectNodes("/*[local-name()='Person']/n1:Name", nsMgr)
Console.WriteLine(Space(4) & "Found " & xNodLst6.Count & " matche(s)")
'Accessing the Name and Age nodes in a namespace agnostic fashion
'This implies that you are assuming that you do not care about the namespace and can be dangerous
Console.WriteLine("Looking for Name Node(s) without the namespace manager using the localName XPath function...")
Dim xNodLst7 As Xml.XmlNodeList = xdoc.SelectNodes("/*[local-name()='Person']/*[local-name()='Name']")
Console.WriteLine(Space(4) & "Found " & xNodLst7.Count & " matche(s)")
Console.ReadLine()
End Sub
And a look at the results
No comments:
Post a Comment