The Attribute Class





The Attribute Class

The Attribute class, shown in Figure, represents an attribute of an element other than one that declares a namespace. Each attribute has these five basic properties:

Local Name

A String accessible through the setName() and getName() methods.

Namespace

A Namespace object that encapsulates both the namespace URI and the prefix. This is accessible through the setNamespace() and getNamespace() methods. For all unprefixed attributes, this is Namespace.NO_NAMESPACE. The prefix, URI, and fully qualified name are separately readable through the getNamespaceURI(), getNamespacePrefix(), and getQualifiedName() convenience methods.

Value

A String that contains the attribute's normalized value. This is accessible through the getValue() and setValue() methods. The unnormalized value is not available. There are also convenience methods that read the attribute value as a double, float, long, int, or boolean.

Parent

The Element that possesses this Attribute. This is accessible through the getParent() and setParent() methods. An Attribute cannot have more than one parent. Before attaching a new parent Element, you must first invoke detach() to remove the Attribute from its current parent.

Type

The Attribute's type, as specified in the DTD. This is one of the ten named constants: Attribute.CDATA_ATTRIBUTE, Attribute.ID_ATTRIBUTE, Attribute.IDREF_ATTRIBUTE, Attribute.IDREFS_ATTRIBUTE, Attribute.ENUMERATED_ATTRIBUTE, and so forth. If the DTD does not specify the attribute's type, JDOM sets the type to Attribute.UNDECLARED_ATTRIBUTE.[3] The getAttributeType() and setAttributeType() methods access this property.

[3] In practice, SAX gets this wrong. It does not distinguish between CDATA type attributes and undeclared attributes. Thus when a SAX parser builds a JDOM Document, no attributes will have type Attribute.UNDECLARED_ATTRIBUTE.

In addition, you can get the Document to which the Attribute belongs with the getDocument() method, although this is not truly independent of the Element to which the attribute is attached.

10 The JDOM Attribute Class
package org.jdom;

public class Attribute implements Serializable, Cloneable {
  public final static int UNDECLARED_ATTRIBUTE = 0;
  public final static int CDATA_ATTRIBUTE      = 1;
  public final static int ID_ATTRIBUTE         = 2;
  public final static int IDREF_ATTRIBUTE      = 3;
  public final static int IDREFS_ATTRIBUTE     = 4;
  public final static int ENTITY_ATTRIBUTE     = 5;
  public final static int ENTITIES_ATTRIBUTE   = 6;
  public final static int NMTOKEN_ATTRIBUTE    = 7;
  public final static int NMTOKENS_ATTRIBUTE   = 8;
  public final static int NOTATION_ATTRIBUTE   = 9;
  public final static int ENUMERATED_ATTRIBUTE = 10;

  protected           String    name;
  protected transient Namespace namespace;
  protected           String    value;
  protected           int       type;
  protected           Object    parent;

  protected Attribute();

  public Attribute(String name, String value,
   Namespace namespace);
  public Attribute(String name, String value, int type,
   Namespace namespace);
  public Attribute(String name, String value);
  public Attribute(String name, String value, int type);

  public Document     getDocument();
  public Element      getParent();
  protected Attribute setParent(Element parent);
  public Attribute    detach();
  public String       getName();
  public Attribute    setName(String name);
  public String       getQualifiedName();
  public String       getNamespacePrefix();
  public String       getNamespaceURI();
  public Namespace    getNamespace();
  public Attribute    setNamespace(Namespace namespace);
  public String       getValue();
  public Attribute    setValue(String value);
  public int          getAttributeType();
  public Attribute    setAttributeType(int type);

  public String        toString();
  public final boolean equals(Object o);
  public final int     hashCode();
  public Object        clone();

  public int     getIntValue() throws DataConversionException;
  public long    getLongValue() throws DataConversionException;
  public float   getFloatValue() throws DataConversionException;
  public double  getDoubleValue() throws DataConversionException;
  public boolean getBooleanValue() throws DataConversionException;

}

Tip

One of the key things to remember when working with attributes, whether in JDOM or any other XML technology, is that unprefixed attributes are never in any namespace. In particular,

  1. Attributes are never in the default namespace.

  2. An attribute is not in the same namespace as its parent element (except in the unusual case where it happens to have the same prefix as its parent element).


At least 90 percent of the time, you will just use the setAttribute(), getAttribute(), and removeAttribute() methods in the Element class rather than using the Attribute class. The only major reason to use the Attribute class directly is if the attribute type matters; for example, when you want to treat an ID-type attribute differently than a CDATA attribute, or a NOTATIONS attribute differently than a NMTOKENS attribute.

For example, consider attribute value normalization. When a parser reports an attribute value to the client application, it adjusts the white space according to the attribute type. Attributes of type CDATA and undeclared attributes preserve all white space. For all other attribute types, white space is trimmed from the edges, and all runs of white space are compressed to a single space. Consider this fact start-tag:

<fact source=" f21 f32   f33 
 f122 f87 f893 ">

If the document's DTD declares that the source attribute has type IDREFS, then the parser will report its value as f21 f32 f33 f122 f87 f893. On the other hand, if the DTD declares that it has type CDATA or does not assign it a type at all, then the parser will report its value with all of the spaces and line breaks intact.

JDOM will accept whatever value the parser initially reports when the document is constructed. However, if attributes are added or their values modified later, then attributes will no longer be in normalized form. To fix this, we can write a method that searches a document for attributes whose type is something other than CDATA and normalizes their space. As usual the method is recursive:

public void normalizeAttributes(Element element) {

  List attributes = element.getAttributes();
  Iterator iterator = attributes.iterator();
  while (iterator.hasNext()) {
    Attribute attribute = (Attribute) iterator.next();
    int type = attribute.getAttributeType();
    if (type != Attribute.CDATA_ATTRIBUTE
     && type != Attribute.UNDECLARED_ATTRIBUTE) {
       String oldValue = attribute.getValue();
       String newValue = Text.normalizeString(oldValue);
       attribute.setValue(newValue);
    }
  }

  List content = element.getContent();
  Iterator children = content.iterator();
  while (children.hasNext()) {
    Object o = children.next();
    if (o instanceof Element) {
      Element child = (Element) o;
      normalizeAttributes(child);
    }
  }

}

The actual normalization is performed by the static Text.normalizeString() method from the Text class.


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows