Reading XML Attributes


Now that you know how to move downward through a document, visiting nodes along the way, let's investigate moving horizontally through the reader, investigating attributes on elements. Since attributes appear adjacent to an element's start tag, I refer to moving through attributes as moving "horizontally" through the XML document.

Reading Attributes without Moving the Reader

One effective way to move through the attributes of an element is to set up a loop and simply read each one sequentially. The XmlTextReader provides properties and accessors to do just this. Listing 10.11 defines a method that searches the current element's attribute list looking for a specified value. The index of the attribute is returned if a matching value is found. String.Empty is returned otherwise .

Listing 10.11
 C# public int SearchAttributes(string value, XmlReader reader) {   if(!reader.HasAttributes)     return -1;   for(int ndx = 0;ndx<reader.AttributeCount;++ndx)   {     if(reader[ndx] == value)       return ndx;   }   return -1; } VB Function SearchAttributes(ByVal value As String, ByVal reader As XmlReader) As Integer    Dim ndx As Integer    If (Not reader.HasAttributes) Then      Return -1    End If   For ndx = 0 To reader.AttributeCount     If (reader(ndx) = value) Then      Return ndx    End If  Next ndx  Return -1 End Function 

Listing 10.11 utilizes three very useful members of the XmlTextReader : HasAttributes , AttributeCount , and the Item indexer. The code uses HasAttributes to check for the presence of attributes. This property is discussed in the section titled "Reading XML Nodes" earlier in this chapter. The code first checks whether the current node even has attributes. If not, -1 is returned, signifying that no match was found. This property returns true if the current node has attributes. False is returned otherwise.

The for loop will sequentially step through each attribute. The upper bound of the loop is set to reader.AttributeCount . This property returns the number of attributes the element contains. This property is relevant only for XmlNodeType.Elements , XmlNodeType.DocumentType , and XmlNodeType.XmlDeclaration . Other nodes cannot have attributes.

Finally, the attribute value is compared to the specified value. If there is a match, the current index of the attribute is returned. The code uses an indexer to retrieve the value of the attribute. The indexer takes an integer representing the index of the attribute and returns the string value of the attribute at that index. The indexer will throw an ArgumentOutOfRangeException if the index is greater than or equal to the AttributeCount .

The item indexer property does not move the reader. Thus, in this example the reader remains on the current node throughout the method. Calling reader. Name after calling the indexer would return the current element's name and not the name of the attribute. In order to retrieve the attribute name, the code would have to move the XmlTextReader to attribute, using one of the horizontal move methods discussed in the next section, "Reading Attributes Using Horizontal Movement."

There are two other item indexers that will retrieve attribute values. The first indexer takes a single string parameter representing the qualified name of the attribute. The second indexer takes two string parameters. The first string parameter represents the local name of the attribute, and the second string parameter represents the namespace URI of the attributes. These indexers do not move the reader. They return String.Empty if the attribute is not found. These indexers are very useful when the name of the attribute is known. They allow the reader to jump directly to the attribute and retrieve its value.

READING THE ATTRIBUTES OF AN XML DECLARATION NODE

The XmlTextReader item indexers are also great for reading the attributes of an XML declaration, the only other node with attributes that will be encountered by the XmlTextReader . DocumentType nodes also have attributes, but the .NET Compact Framework's XmlTextReader does not allow documents with DTDs to be read. Listing 10.12 demonstrates reading the Standalone property of an XML declaration node.


Listing 10.12
 C# if(XmlNodeType.XmlDeclaration == reader.NodeType)      MessageBox.Show("Standalone: " + reader["standalone"]) VB If (XmlNodeType.XmlDeclaration = reader.NodeType) Then   MessageBox.Show("Standalone: " & reader("standalone")) End If 

Reading Attributes by Using Horizontal Movement

In the previous section, we examined methods for reading the attributes of an element without actually moving the XmlTextReader . Now let us investigate the methods that read attributes by moving the reader.

The MoveToAttribute method allows you to move from an element to its attributes. This method functions much like the XmlTextReader item indexer, except, of course, that it moves the reader to the attribute. Since the reader is actually moved to the attribute, all of the methods and properties operate on the attribute and not on the container element. This means that calling the Name property after calling the MoveToAttribute method will return the name of the attribute and not the name of the element containing the attribute.

Like the XmlTextReader indexer, MoveToAttribute comes in three flavors. One overload takes a single integer parameter as the index of the attribute. And like its indexer counterpart , this method will throw a System.ArgumentOutOfRangeException if the index is less than zero or greater than or equal to AttributeCount . The next overload takes one string parameter as the qualified name of the attribute. The method returns true if an attribute with a matching name is found, false if otherwise. The reader is not moved if no attribute is found and false is returned. The final overload of MoveToAttribute takes two strings as parameters. The first represents the local name of the attribute and the second is the namespace URI of the attribute. Again, true is returned if the attribute was found and false if no attribute was found. Like its one parameter counterpart, the reader is not moved if no attribute is found.

Let's use the MoveToAttribute method to write another version of the SearchAttributes method from Listing 10.11. The version of SearchAttributes in Listing 10.13 will return the name of the matching attribute instead of the attribute's index.

Listing 10.13
 C# public string SearchAttributes(string value, XmlReader reader) {   if(!reader.HasAttributes)     return string.Empty;   for(int ndx = 0;ndx<reader.AttributeCount;++ndx)   {     reader.MoveToAttribute(ndx);     if(reader.Value == value)       return reader.Name;   }   return string.Empty; } VB Function SearchAttributes(ByVal value As String, ByVal reader As XmlReader) As String   Dim ndx As Integer   If (Not reader.HasAttributes) Then     Return String.Empty   End If   For ndx = 0 To reader.AttributeCount     reader.MoveToAttribute(ndx)     If (reader.Value = value) Then       Return reader.Name     End If   Next ndx   Return String.Empty End Function 

The code should look very familiar, except for the return type of the SearchAttributes method. We call MoveToAttribute with the index of the attribute we want to move to. Since the XmlTextReader is actually moved to the attribute, we can call Name to return the name of the attribute.

The XmlTextReader provides two additional methods for reading attributes that do not require knowing the index or the name of the attribute. The MoveToFirstAttribute method moves the reader from the current position to the first attribute on the current element. If there are no attributes, this method returns false and the reader does not move. If there is an attribute in the first position, true is returned and the reader is moved.

The MoveToNextAttribute method moves the reader to the next attribute on the element. If the current node is pointed to an element, this method is equivalent to MoveToFirstAttribute . If there is no next attribute, false is returned and the reader does not move. If a next attribute exists, the reader is moved and true is returned.

These two methods are very effective when navigating through an element's attributes. We revisit the SearchAttributes method from Listing 10.11 to demonstrate MoveToFirstAttribute and MoveToNextAttribute . The code in Listing 10.14 uses the two methods to loop through the attributes instead of using attribute indexes.

Listing 10.14
 C# public string SearchAttributes(string value, XmlReader reader) {   if(!reader.MoveToFirstAttribute)     return string.Empty;   do{     if(reader.Value == value)       return reader.Name;   }while(reader.MoveToNextAttribute());   return string.Empty; } VB Function SearchAttributes(ByVal value As String, ByVal reader As XmlReader) As String   If (Not reader.MoveToFirstAttribute) Then     Return String.Empty   End If   Do     If (reader.Value = value) Then       Return reader.Name     End If   Loop While (reader.MoveToNextAttribute())   Return String.Empty 

Again, this code is similar to the last two versions. We call MoveToFirstAttributes to get the reader to go to the first attribute. The return value of the method is used to check whether an attribute exists at all. The for loop has been replaced with a do loop that calls MoveToNextAttribute until there are no more attributes, at which time the MoveToNextAttributes returns false.

This version of SearchAttributes seems to be fairly robust. As long as the reader is located on a node with attributes, the code should always find a match if one is present. There is one subtle side-effect of this current version. The astute reader (human) will notice that the reader (text) could be left anywhere on the current element. It would be nice if the reader were always left pointing to the element containing the attributes being searched. The .NET Compact Framework provides the MoveToElement method to perform the aforementioned task. This method returns true if the reader is positioned on an attribute. False is returned if the reader is not positioned on an attribute, in which case the reader is not moved. Listing 10.15 is yet another version of SearchAttributes that uses MoveToElement to guarantee that reader is left on the current element after the attributes are searched.

Listing 10.15
 C# public string SearchAttributes(string value, XmlReader reader) {     string ret = string.Empty;     if(!reader.MoveToFirstAttribute)       return ret;     do{       if(reader.Value == value)       {         ret = reader.Name;         break;       }     }while(reader.MoveToNextAttribute());     reader.MoveToElement();     return ret; } VB Function SearchAttributes(ByVal value As String, ByVal reader As XmlReader) As String   Dim ret As String   ret = String.Empty   If (Not reader.MoveToFirstAttribute) Then     Return ret   End If   Do     If (reader.Value = value) Then       ret = reader.Name       Exit Do     End If   Loop While (reader.MoveToNextAttribute())   reader.MoveToElement()   Return ret 


Microsoft.NET Compact Framework Kick Start
Microsoft .NET Compact Framework Kick Start
ISBN: 0672325705
EAN: 2147483647
Year: 2003
Pages: 206

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net