Namespaces, Why Does It Always Have To Be Namespaces?

I’ll be honest, I LOATHE namespaces in XML.  I haven’t seen a case where I needed to use them to differentiate between identically-named elements in different contexts.  So often, the document declares a namespace at the top and never overrides it.  In that case, why use it?

Why do I hate it?

It breaks XPath navigation.  Or, at least it breaks my rudimentary grasp of XPath.  Someone sent a Lync topology builder file (it’s all 192.168.x.x and 10.x.x.x non-routable addresses, anyhow) with a simple question: how to get the IPAddress attribute value for <NetInterface> elements.

$xml.SelectNodes(“//NetInterface”) | Select-Object –Property IPAddress

But, nooooooooooooooooo…

Here are some of the answers that I’ve seen:

This is one that plays nice with namespaces.  Notice that it’s not XPath.

 $xml = [xml]"$(gc tbxml.xml)"
($xml | Select-Xml '(//wt:CentralSites)[1]/wt:CentralSite[2]/t:Location' -Namespace @{
    wt = 'urn:schema:Microsoft.Rtc.Management.Deploy.WritableTopology.2008'
    t = 'urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008'
}).Node 

Here’s one that dispenses with namespaces and XPath and just uses the DOM (Document Object Model) to navigate the XML:

 $xml = [xml](gc tbxml.xml)

$centralsite = $xml.TopologyBuilder.OriginalTopology.PartialTopology.CentralSites.CentralSite 
| ? { $_.Name.InnerXml -eq "CentralSite1" }

if ($centralsite)
{
    $centralsite.Clusters.Cluster.Machines.Machine.NetInterface | 
    Select-Object -Property @{
        Name = "FQDN"; 
        Expression = { $_.ParentNode.Fqdn; }
    },@{
        Name = "IPAddress";
        Expression = { $_.IPAddress; }
    }
}

My contribution to the ruckus at least uses XPath, albeit inefficiently:

 $xml = (Get-Content -Path YaddaYadda.xml) -as [xml];

$objects = $xml.SelectNodes("//*[name()='NetInterface']") | 
Select-Object @{ 
    n = 'MachineFQDN'; e = { $_.ParentNode.Fqdn.Tolower(); }
}, @{ 
    n = 'ClusterFQDN'; e = { $_.ParentNode.ParentNode.ParentNode.Fqdn.ToLower(); }
}, IPAddress, InterfaceNumber, InterfaceSide;