Thursday, January 10, 2008

Get XML Nodes that do not have a specific attribute

Alright after those design patterns, this one might strike as a real lightweight entry. Recently, I needed a method to identify all XML nodes that did not have a specific atrribute. Well, the first approach was a simple IF clause to verify if the attribute object is nothing. This did a fine job till I realized that I could a better approach, call it a result of refactoring or just an afterthought.

Sample code

  Sub Main()

    'Sample XML island

    Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder

    sb.AppendLine("<items>")

    sb.AppendLine("  <item type='Pencil' qty='5' IsCanceled='1' />")

    sb.AppendLine("  <item type='Pen' qty='2' />")

    sb.AppendLine("  <item type='Book' qty='1' />")

    sb.AppendLine("  <item type='Pencil' qty='3' />")

    sb.AppendLine("</items>")

 

    Dim xDoc As Xml.XmlDocument = New Xml.XmlDocument

    xDoc.LoadXml(sb.ToString)

 

    Console.WriteLine("Original XML Content")

    Console.WriteLine(sb.ToString)

 

    'Original Strategy

    Console.WriteLine("Active list of items")

    Dim xNodLst As Xml.XmlNodeList = xDoc.SelectNodes("/items/item")

    For Each xNod As Xml.XmlNode In xNodLst

      If xNod.Attributes("IsCanceled") Is Nothing Then

        Console.WriteLine("{0} [{1}]", xNod.Attributes("type").Value, xNod.Attributes("qty").Value)

      End If

    Next

    Console.WriteLine()

 

    'Alternate Strategy

    Console.WriteLine("Active list of items (Alternate)")

    Dim xNodAltLst As Xml.XmlNodeList = xDoc.SelectNodes("/items/item[not (@IsCanceled)]")

    For Each xNod As Xml.XmlNode In xNodAltLst

      Console.WriteLine("{0} [{1}]", xNod.Attributes("type").Value, xNod.Attributes("qty").Value)

    Next

 

    Console.ReadLine()

  End Sub



In this example, I have eliminated nodes that do not have the IsCanceled attribute. The exact value of the attribute was not relevant to me, its existence was reason enough to have it eliminated from my result list.

A look at the execution result


Of course, if you wanted to include only nodes that had a specific attribute, you guessed right, just take the 'not' keyword out of the query -

Dim xNodAltLst As Xml.XmlNodeList = xDoc.SelectNodes("/items/item[@IsCanceled]")

No comments: