The Attr Interface


Probably 90 percent of the time, everything you need to do with attributes can be done purely through the various attribute methods of the Element interface. However, occasionally the Attr interface comes in handy. An Attr object represents an attribute, whether explicitly included in the document or present by default from the schema.

Example 11.15 summarizes the Attr interface. In addition to methods inherited from the Node superinterface, Attr includes methods to do the following:

  • Get the full name of the attribute (including a prefix, if any)

  • Determine whether the attribute was specified in the document or merely appears by default from the DTD or schema

  • Get the element that contains this attribute

  • Get the value of the attribute.

Entity and character references in the value are resolved, but white space is not normalized. There's also a method that can change the value of this attribute. This throws a DOMException if the attribute is read only, as it might be if this attribute belonged to an element in a read-only entity reference node.

Example 11.15 The Attr Interface
 package org.w3c.dom; public interface Attr extends Node {   public String  getName();  // Prefixed name   public String  getValue();   public Element getOwnerElement();   public boolean getSpecified();   public void    setValue(String value) throws DOMException; } 

The key thing to watch out for when working with attributes in DOM is that they are not considered to be children of the elements that contain them. Furthermore, unlike the XPath data model, the elements that contain them are not their parents either. In DOM, attributes have no parents, so invoking getParent() on an Attr always returns null.

In DOM terminology, an attribute that is actually placed on the start-tag of an element is called specified. An attribute that is present by default from the DTD or schema is not specified. You can tell which is which by invoking the getSpecified() method. This is one of the few things you can do with an Attr object that you can't do with the owning Element object.

Some interoperability problems in XML relate to the fact that some parsers validate and others don't. If validation were only about checking constraints, then this wouldn't be a big problem, but unfortunately validation does more than that. In particular it assigns default attribute values to elements. These attributes may be seen by a validating parser but not by a nonvalidating parser. As an example of this interface, I'm going to write a program that converts unspecified attributes into specified attributes to improve interoperability. Note that an attribute modified or added programmatically in DOM is always specified, even if it has the same value as the default attribute in the DTD. If you delete an attribute for which the DTD provides a default value, then DOM will insert an attribute node with the default value. Thus it's impossible to eliminate a default attribute. Example 11.16 demonstrates . [5]

[5] I admit that this example is a little contrived. Reading each value and writing the same value back out again would be easier.

Example 11.16 Specifying All Attributes
 import org.w3c.dom.*; public class AttributeUtility {   // Recursively descend the tree replacing all unspecified   // attributes with specified attributes   public static void specifyAttributes(Node node) {     int type = node.getNodeType();     if (type == Node.ELEMENT_NODE) {                 // the only type with attributes       Element element = (Element) node;       NamedNodeMap attributes = element.getAttributes();       Document factory = node.getOwnerDocument();       for (int i = 0; i < attributes.getLength(); i++) {         Attr attribute = (Attr) attributes.item(i);         if (!attribute.getSpecified()) {           // We can't change the specified property of an           // attribute in DOM2. However, attributes are specified           // by default, so if we delete the old attribute and           // add a new one with the same name and value, or           // change the attribute's value (even to the same           // thing), the effect is what we're looking for.           String name = attribute.getName();           String value = attribute.getValue();           Attr specifiedAttribute = factory.createAttribute(name);           specifiedAttribute.setValue(value);           element.setAttributeNode(specifiedAttribute);           // This replaces the old attribute with the same name.         }       } // end for     } // end if     if (node.hasChildNodes()) {       NodeList children = node.getChildNodes();       for (int i = 0; i < children.getLength(); i++) {         Node child = children.item(i);         specifyAttributes(child);       } // end for     } // end if   }  // end specifyAttributes() } 

This program simply recursively descends the tree beneath a node, looking for elements. It scans each element's attributes. If any of those attributes are not specified, then the attribute is deleted and replaced with a copy.

DOM2 is missing one crucial feature for working with attributes. It cannot tell you the type of the attribute as declared in the DTD. That is, you cannot find out if an attribute is CDATA, ID, IDREF, NMTOKEN, and so forth.



Processing XML with Java. A Guide to SAX, DOM, JDOM, JAXP, and TrAX
Processing XML with Javaв„ў: A Guide to SAX, DOM, JDOM, JAXP, and TrAX
ISBN: 0201771861
EAN: 2147483647
Year: 2001
Pages: 191

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