The Attribute class, shown in Example 15.10, represents an attribute of an element other than one that declares a namespace. Each attribute has these five basic properties:
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. Example 15.10 The JDOM Attribute Classpackage 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,
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. |