Logo Search packages:      
Sourcecode: jericho-html version File versions  Download package

Element.java

// Jericho HTML Parser - Java based library for analysing and manipulating HTML
// Version 2.2
// Copyright (C) 2006 Martin Jericho
// http://sourceforge.net/projects/jerichohtml/
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// http://www.gnu.org/copyleft/lesser.html
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package au.id.jericho.lib.html;

import java.util.*;

/**
 * Represents an <a target="_blank" href="http://www.w3.org/TR/html401/intro/sgmltut.html#h-3.2.1">element</a>
 * in a specific {@linkplain Source source} document, which encompasses a {@linkplain #getStartTag() start tag},
 * an optional {@linkplain #getEndTag() end tag} and all {@linkplain #getContent() content} in between.
 * <p>
 * The term <i><a name="Normal">normal element</a></i> refers to an element having a {@linkplain #getStartTag() start tag}
 * with a {@linkplain StartTag#getStartTagType() type} of {@link StartTagType#NORMAL}.
 * This comprises all {@linkplain HTMLElements HTML elements} and <a href="HTMLElements.html#NonHTMLElement">non-HTML elements</a>.
 * <p>
 * <code>Element</code> instances are obtained using one of the following methods:
 * <ul>
 *  <li>{@link StartTag#getElement()}
 *  <li>{@link EndTag#getElement()}
 *  <li>{@link Segment#findAllElements()}
 *  <li>{@link Segment#findAllElements(String name)}
 *  <li>{@link Segment#findAllElements(StartTagType)}
 * </ul>
 * See also the {@link HTMLElements} class, and the 
 * <a target="_blank" href="http://www.w3.org/TR/REC-xml#dt-element">XML 1.0 specification for elements</a>.
 * <h3><a name="Structure">Element Structure</a></h3>
 * <p>
 * The three possible structures of an element are listed below:
 * <dl class="Separated">
 *  <dt><a name="SingleTag">Single Tag Element</a>:
 *   <dd>
 *    The element consists only of a single {@linkplain #getStartTag() start tag} and has no {@linkplain #getContent() element content}
 *    (although the start tag itself may have {@linkplain StartTag#getTagContent() tag content}).
 *    <br />{@link #getEndTag()}<code>==null</code>
 *    <br />{@link #isEmpty()}<code>==true</code>
 *    <br />{@link #getEnd() getEnd()}<code>==</code>{@link #getStartTag()}<code>.</code>{@link #getEnd() getEnd()}
 *    <p>
 *    This occurs in the following situations:
 *    <ul class="Unseparated">
 *     <li>An <a href="HTMLElements.html#HTMLElement">HTML element</a> for which the {@linkplain HTMLElements#getEndTagForbiddenElementNames() end tag is forbidden}.
 *     <li>An <a href="HTMLElements.html#HTMLElement">HTML element</a> for which the {@linkplain HTMLElements#getEndTagRequiredElementNames() end tag is required},
 *      but the end tag is not present in the source document.
 *     <li>An <a href="HTMLElements.html#HTMLElement">HTML element</a> for which the {@linkplain HTMLElements#getEndTagOptionalElementNames() end tag is optional},
 *      where the <a href="#ImplicitlyTerminated">implicitly terminating</a> tag is situated immediately after the element's
 *      {@linkplain #getStartTag() start tag}.
 *     <li>An {@linkplain #isEmptyElementTag() empty element tag}
 *     <li>A <a href="HTMLElements.html#NonHTMLElement">non-HTML element</a> that is not an {@linkplain #isEmptyElementTag() empty element tag} but is missing its end tag.
 *     <li>An element with a start tag of a {@linkplain StartTag#getStartTagType() type} that does not define a
 *     {@linkplain StartTagType#getCorrespondingEndTagType() corresponding end tag type}.
 *     <li>An element with a start tag of a {@linkplain StartTag#getStartTagType() type} that does define a
 *     {@linkplain StartTagType#getCorrespondingEndTagType() corresponding end tag type} but is missing its end tag.
 *    </ul>
 *  <dt><a name="ExplicitlyTerminated">Explicitly Terminated Element</a>:
 *   <dd>
 *    The element consists of a {@linkplain #getStartTag() start tag}, {@linkplain #getContent() content},
 *    and an {@linkplain #getEndTag() end tag}.
 *    <br />{@link #getEndTag()}<code>!=null</code>.
 *    <br />{@link #isEmpty()}<code>==false</code> (provided the end tag doesn't immediately follow the start tag)
 *    <br />{@link #getEnd() getEnd()}<code>==</code>{@link #getEndTag()}<code>.</code>{@link #getEnd() getEnd()}.
 *    <p>
 *    This occurs in the following situations, assuming the start tag's matching end tag is present in the source document:
 *    <ul class="Unseparated">
 *     <li>An <a href="HTMLElements.html#HTMLElement">HTML element</a> for which the end tag is either
 *      {@linkplain HTMLElements#getEndTagRequiredElementNames() required} or {@linkplain HTMLElements#getEndTagOptionalElementNames() optional}.
 *     <li>A <a href="HTMLElements.html#NonHTMLElement">non-HTML element</a> that is not an {@linkplain #isEmptyElementTag() empty element tag}.
 *     <li>An element with a start tag of a {@linkplain StartTag#getStartTagType() type} that defines a
 *     {@linkplain StartTagType#getCorrespondingEndTagType() corresponding end tag type}.
 *    </ul>
 *  <dt><a name="ImplicitlyTerminated">Implicitly Terminated Element</a>:
 *   <dd>
 *    The element consists of a {@linkplain #getStartTag() start tag} and {@linkplain #getContent() content},
 *    but no {@linkplain #getEndTag() end tag}.
 *    <br />{@link #getEndTag()}<code>==null</code>.
 *    <br />{@link #isEmpty()}<code>==false</code>
 *    <br />{@link #getEnd() getEnd()}<code>!=</code>{@link #getStartTag()}<code>.</code>{@link #getEnd() getEnd()}.
 *    <p>
 *    This only occurs in an <a href="HTMLElements.html#HTMLElement">HTML element</a> for which the
 *    {@linkplain HTMLElements#getEndTagOptionalElementNames() end tag is optional}.
 *    <p>
 *    The element ends at the start of a tag which implies the termination of the element, called the <i>implicitly terminating tag</i>.
 *    If the implicitly terminating tag is situated immediately after the element's {@linkplain #getStartTag() start tag},
 *    the element is classed as a <a href="#SingleTag">single tag element</a>.
 *    <p>
 *    See the <a href="Element.html#ParsingRulesHTMLEndTagOptional">element parsing rules for HTML elements with optional end tags</a>
 *    for details on which tags can implicitly terminate a given element.
 *    <p>
 *    See also the documentation of the {@link HTMLElements#getEndTagOptionalElementNames()} method.
 * </dl>
 * <h3><a name="ParsingRules">Element Parsing Rules</a></h3>
 * The following rules describe the algorithm used in the {@link StartTag#getElement()} method to construct an element.
 * The detection of the start tag's matching end tag or other terminating tags always takes into account the possible nesting of elements.
 * <p>
 * <ul class="Separated">
 *  <li>
 *   If the start tag has a {@linkplain StartTag#getStartTagType() type} of {@link StartTagType#NORMAL}:
 *   <ul>
 *    <li>
 *     If the {@linkplain StartTag#getName() name} of the start tag matches one of the
 *     recognised {@linkplain HTMLElementName HTML element names} (indicating an <a href="HTMLElements.html#HTMLElement">HTML element</a>):
 *     <ul>
 *      <li>
 *       <a name="ParsingRulesHTMLEndTagForbidden"></a>
 *       If the end tag for an element of this {@linkplain StartTag#getName() name} is
 *       {@linkplain HTMLElements#getEndTagForbiddenElementNames() forbidden},
 *       the parser does not conduct any search for an end tag and a <a href="#SingleTag">single tag element</a> is created.
 *      <li>
 *       <a name="ParsingRulesHTMLEndTagRequired"></a>
 *       If the end tag for an element of this {@linkplain StartTag#getName() name} is 
 *       {@linkplain HTMLElements#getEndTagRequiredElementNames() required}, the parser searches for the start tag's matching end tag.
 *       <ul class="Unseparated">
 *        <li>
 *         If the matching end tag is found, an <a href="#ExplicitlyTerminated">explicitly terminated element</a> is created.
 *        <li>
 *         If no matching end tag is found, the source document is not valid HTML and the incident is
 *         {@linkplain Source#setLogWriter(Writer) logged} as a missing required end tag.
 *         In this situation a <a href="#SingleTag">single tag element</a> is created.
 *       </ul>
 *      <li>
 *       <a name="ParsingRulesHTMLEndTagOptional"></a>
 *       If the end tag for an element of this {@linkplain StartTag#getName() name} is
 *       {@linkplain HTMLElements#getEndTagOptionalElementNames() optional}, the parser searches not only for the start tag's matching end tag,
 *       but also for any other tag that <a href="#ImplicitlyTerminated">implicitly terminates</a> the element.
 *       <br />For each tag (<i>T2</i>) following the start tag (<i>ST1</i>) of this element (<i>E1</i>):
 *       <ul class="Unseparated">
 *        <li>
 *         If <i>T2</i> is a start tag:
 *         <ul>
 *          <li>
 *           If the {@linkplain StartTag#getName() name} of <i>T2</i> is in the list of
 *           {@linkplain HTMLElements#getNonterminatingElementNames(String) non-terminating element names} for <i>E1</i>,
 *           then continue evaluating tags from the {@linkplain Element#getEnd() end} of <i>T2</i>'s corresponding
 *           {@linkplain StartTag#getElement() element}.
 *          <li>
 *           If the {@linkplain StartTag#getName() name} of <i>T2</i> is in the list of
 *           {@linkplain HTMLElements#getTerminatingStartTagNames(String) terminating start tag names} for <i>E1</i>,
 *           then <i>E1</i> ends at the {@linkplain StartTag#getBegin() beginning} of <i>T2</i>.
 *           If <i>T2</i> follows immediately after <i>ST1</i>, a <a href="#SingleTag">single tag element</a> is created,
 *           otherwise an <a href="#ImplicitlyTerminated">implicitly terminated element</a> is created.
 *         </ul>
 *        <li>
 *         If <i>T2</i> is an end tag:
 *         <ul>
 *          <li>
 *           If the {@linkplain EndTag#getName() name} of <i>T2</i> is the same as that of <i>ST1</i>,
 *           an <a href="#ExplicitlyTerminated">explicitly terminated element</a> is created.
 *          <li>
 *           If the {@linkplain EndTag#getName() name} of <i>T2</i> is in the list of
 *           {@linkplain HTMLElements#getTerminatingEndTagNames(String) terminating end tag names} for <i>E1</i>,
 *           then <i>E1</i> ends at the {@linkplain EndTag#getBegin() beginning} of <i>T2</i>.
 *           If <i>T2</i> follows immediately after <i>ST1</i>, a <a href="#SingleTag">single tag element</a> is created,
 *           otherwise an <a href="#ImplicitlyTerminated">implicitly terminated element</a> is created.
 *         </ul>
 *        <li>
 *         If no more tags are present in the source document, then <i>E1</i> ends at the end of the file, and an
 *         <a href="#ImplicitlyTerminated">implicitly terminated element</a> is created.
 *       </ul>
 *     </ul>
 *     Note that the syntactical indication of an {@linkplain StartTag#isEmptyElementTag() empty-element tag} in the start tag
 *     is ignored when determining the end of <a href="HTMLElements.html#HTMLElement">HTML elements</a>.
 *     See the documentation of the {@link #isEmptyElementTag()} method for more information.
 *    <li>
 *     If the {@linkplain StartTag#getName() name} of the start tag does not match one of the
 *     recognised {@linkplain HTMLElementName HTML element names} (indicating a <a href="HTMLElements.html#NonHTMLElement">non-HTML element</a>):
 *     <ul>
 *      <li>
 *       If the start tag is an {@linkplain StartTag#isEmptyElementTag() empty-element tag},
 *       the parser does not conduct any search for an end tag and a <a href="#SingleTag">single tag element</a> is created.
 *      <li>
 *       Otherwise, section <a target="_blank" href="http://www.w3.org/TR/REC-xml#CleanAttrVals">3.1</a>
 *       of the XML 1.0 specification states that a matching end tag MUST be present, and
 *       the parser searches for the start tag's matching end tag.
 *       <ul class="Unseparated">
 *        <li>
 *         If the matching end tag is found, an <a href="#ExplicitlyTerminated">explicitly terminated element</a> is created.
 *        <li>
 *         If no matching end tag is found, the source document is not valid XML and the incident is
 *         {@linkplain Source#setLogWriter(Writer) logged} as a missing required end tag.
 *         In this situation a <a href="#SingleTag">single tag element</a> is created.
 *       </ul>
 *     </ul>
 *   </ul>
 *  <li>
 *   If the start tag has any {@linkplain StartTag#getStartTagType() type} other than {@link StartTagType#NORMAL}:
 *   <ul>
 *    <li>
 *     If the start tag's type does not define a {@linkplain StartTagType#getCorrespondingEndTagType() corresponding end tag type},
 *     the parser does not conduct any search for an end tag and a <a href="#SingleTag">single tag element</a> is created.
 *    <li>
 *     If the start tag's type does define a {@linkplain StartTagType#getCorrespondingEndTagType() corresponding end tag type},
 *     the parser assumes that a matching end tag is required and searches for it.
 *     <ul class="Unseparated">
 *      <li>
 *       If the matching end tag is found, an <a href="#ExplicitlyTerminated">explicitly terminated element</a> is created.
 *      <li>
 *       If no matching end tag is found, the missing required end tag is {@linkplain Source#setLogWriter(Writer) logged}
 *       and a <a href="#SingleTag">single tag element</a> is created.
 *     </ul>
 *   </ul>
 * </ul>
 * @see HTMLElements
 */
00220 public final class Element extends Segment implements HTMLElementName {
      private final StartTag startTag;
      private final EndTag endTag;
      private Segment content=null;
      Element parentElement=Element.NOT_CACHED;
      private int depth=-1;
      
      static final Element NOT_CACHED=new Element();

      Element(final Source source, final StartTag startTag, final EndTag endTag) {
            super(source, startTag.begin, endTag==null ? startTag.end : endTag.end);
            this.startTag=startTag;
            this.endTag=(endTag==null || endTag.length()==0) ? null : endTag;
      }

      private Element() {
            startTag=null;
            endTag=null;
      }

      /**
       * Returns the parent of this element in the document element hierarchy.
       * <p>
       * The {@link Source#fullSequentialParse()} method should be called after construction of the <code>Source</code> object if this method is to be used.
       * <p>
       * This method returns <code>null</code> for a <a href="Source.html#TopLevelElement">top-level element</a>,
       * as well as any element formed from a {@linkplain TagType#isServerTag() server tag}, regardless of whether it is nested inside a normal element.
       * <p>
       * See the {@link Source#getChildElements()} method for more details.
       *
       * @return the parent of this element in the document element hierarchy, or <code>null</code> if this element is a <a href="Source.html#TopLevelElement">top-level element</a>.
       * @see #getChildElements()
       */
00253       public Element getParentElement() {
            if (parentElement==Element.NOT_CACHED) {
                  source.getChildElements();
                  if (parentElement==Element.NOT_CACHED) parentElement=null;
            }
            return parentElement;
      }

      /**
       * Returns a list of the immediate children of this element in the document element hierarchy.
       * <p>
       * The objects in the list are all of type {@link Element}.
       * <p>
       * See the {@link Source#getChildElements()} method for more details.
       *
       * @return a list of the immediate children of this element in the document element hierarchy, guaranteed not <code>null</code>.
       * @see #getParentElement()
       */
00271       public final List getChildElements() {
            return childElements!=null ? childElements : getChildElements(-1);
      }

      final List getChildElements(int depth) {
            if (depth!=-1) this.depth=depth;
            if (childElements==null) {
                  if (!Config.IncludeServerTagsInElementHierarchy && end==startTag.end) {
                        childElements=Collections.EMPTY_LIST;
                  } else {
                        final int childDepth=(depth==-1 ? -1 : depth+1);
                        childElements=new ArrayList();
                        int pos=Config.IncludeServerTagsInElementHierarchy ? begin+1 : startTag.end;
                        final int maxChildBegin=(Config.IncludeServerTagsInElementHierarchy || endTag==null) ? end : endTag.begin;
                        while (true) {
                              final StartTag childStartTag=source.findNextStartTag(pos);
                              if (childStartTag==null || childStartTag.begin>=maxChildBegin) break;
                              if (Config.IncludeServerTagsInElementHierarchy) {
                                    if (childStartTag.begin<startTag.end && !childStartTag.getTagType().isServerTag() && !startTag.getTagType().isServerTag()) {
                                          // A start tag is found within another start tag, but neither is a server tag.
                                          // This only legitimately happens in very rare cases like entity definitions in doctype.
                                          // We don't want to include the child elements in the hierarchy.
                                          pos=childStartTag.end;
                                          continue;
                                    }
                              } else if (childStartTag.getTagType().isServerTag()) {
                                    pos=childStartTag.end;
                                    continue;
                              }
                              final Element childElement=childStartTag.getElement();
                              childElement.parentElement=this;
                              if (childElement.end>end && source.isLoggingEnabled()) source.log("Child element "+childElement.getDebugInfo()+" extends beyond end of parent "+getDebugInfo());
                              childElements.add(childElement);
                              childElement.getChildElements(childDepth);
                              pos=childElement.end;
                        }
                  }
            }
            return childElements;
      }

      /**
       * Returns the nesting depth of this element in the document element hierarchy.
       * <p>
       * The {@link Source#fullSequentialParse()} method should be called after construction of the <code>Source</code> object if this method is to be used.
       * <p>
       * A <a href="Source.html#TopLevelElement">top-level element</a> has a nesting depth of <code>0</code>.
       * <p>
       * An element formed from a {@linkplain TagType#isServerTag() server tag} always have a nesting depth of <code>0</code>,
       * regardless of whether it is nested inside a normal element.
       * <p>
       * See the {@link Source#getChildElements()} method for more details.
       *
       * @return the nesting depth of this element in the document element hierarchy.
       * @see #getParentElement()
       */
00327       public int getDepth() {
            if (depth==-1) {
                  getParentElement();
                  if (depth==-1) depth=0;
            }
            return depth;
      }

      /**
       * Returns the segment representing the <a target="_blank" href="http://www.w3.org/TR/REC-xml#dt-content">content</a> of the element.
       * <p>
       * This segment spans between the end of the start tag and the start of the end tag.
       * If the end tag is not present, the content reaches to the end of the element.
       * <p>
       * Note that before version 2.0 this method returned <code>null</code> if the element was {@linkplain #isEmpty() empty},
       * whereas now a zero-length segment is returned.
       *
       * @return the segment representing the content of the element, guaranteed not <code>null</code>.
       */
00346       public Segment getContent() {
            if (content==null) content=new Segment(source,startTag.end,getContentEnd());
            return content;
      }

      /**
       * Returns the start tag of the element.
       * @return the start tag of the element.
       */
00355       public StartTag getStartTag() {
            return startTag;
      }

      /**
       * Returns the end tag of the element.
       * <p>
       * If the element has no end tag this method returns <code>null</code>.
       *
       * @return the end tag of the element, or <code>null</code> if the element has no end tag.
       */
00366       public EndTag getEndTag() {
            return endTag;
      }

      /**
       * Returns the {@linkplain StartTag#getName() name} of the {@linkplain #getStartTag() start tag} of this element, always in lower case.
       * <p>
       * This is equivalent to {@link #getStartTag()}<code>.</code>{@link StartTag#getName() getName()}.
       * <p>
       * See the {@link Tag#getName()} method for more information.
       *
       * @return the name of the {@linkplain #getStartTag() start tag} of this element, always in lower case.
       */
00379       public String getName() {
            return startTag.getName();
      }

      /**
       * Indicates whether this element has zero-length {@linkplain #getContent() content}.
       * <p>
       * This is equivalent to {@link #getContent()}<code>.</code>{@link Segment#length() length()}<code>==0</code>.
       * <p>
       * Note that this is a broader definition than that of both the
       * <a target="_blank" href="http://www.w3.org/TR/html401/intro/sgmltut.html#didx-element-4">HTML definition of an empty element</a>,
       * which is only those elements whose end tag is {@linkplain HTMLElements#getEndTagForbiddenElementNames() forbidden}, and the
       * <a target="_blank" href="http://www.w3.org/TR/REC-xml#dt-empty">XML definition of an empty element</a>,
       * which is "either a start-tag immediately followed by an end-tag, or an {@linkplain #isEmptyElementTag() empty-element tag}".
       * The other possibility covered by this property is the case of an <a href="HTMLElements.html#HTMLElement">HTML element</a> with an
       * {@linkplain HTMLElements#getEndTagOptionalElementNames() optional} end tag that is immediately followed by another tag that implicitly 
       * terminates the element.
       *
       * @return <code>true</code> if this element has zero-length {@linkplain #getContent() content}, otherwise <code>false</code>.
       * @see #isEmptyElementTag()
       */
00400       public boolean isEmpty() {
            return startTag.end==getContentEnd();
      }

      /**
       * Indicates whether this element is an <a target="_blank" href="http://www.w3.org/TR/REC-xml#dt-eetag">empty-element tag</a>.
       * <p>
       * It is signified by an {@linkplain #isEmpty() empty} element with the characters "<code>/&gt;</code>" at the end of the
       * {@linkplain #getStartTag() start tag}.
       * <p>
       * This is equivalent to {@link #isEmpty()}<code> && </code>{@link #getStartTag()}<code>.</code>{@link StartTag#isEmptyElementTag() isEmptyElementTag()}.
       * <p>
       * The {@link StartTag#isEmptyElementTag()} property only checks whether the start tag syntactically an
       * <a target="_blank" href="http://www.w3.org/TR/REC-xml#dt-eetag">empty-element tag</a>, whereas this property also makes sure
       * the element is in fact {@linkplain #isEmpty() empty}.
       * <p>
       * A syntactical empty-element tag that is not actually empty can occur if the end tag of an <a href="HTMLElements.html#HTMLElement">HTML element</a>
       * is either {@linkplain HTMLElements#getEndTagRequiredElementNames() required} or {@linkplain HTMLElements#getEndTagOptionalElementNames() optional},
       * but the start tag is erroneously terminated with the characters "<code>/&gt;</code>" in the source document.
       * All major browsers ignore the syntactical hint of an empty element in this case, even in an
       * <a target="_blank" href="http://www.w3.org/TR/xhtml1/">XHTML</a> document, so this parser does the same.
       *
       * @return <code>true</code> if this element is an <a target="_blank" href="http://www.w3.org/TR/REC-xml#dt-eetag">empty-element tag</a>, otherwise <code>false</code>.
       */
00424       public boolean isEmptyElementTag() {
            return isEmpty() && startTag.isEmptyElementTag();
      }

      /**
       * Returns the attributes specified in this element's start tag.
       * <p>
       * This is equivalent to {@link #getStartTag()}<code>.</code>{@link StartTag#getAttributes() getAttributes()}.
       *
       * @return the attributes specified in this element's start tag.
       * @see StartTag#getAttributes()
       */
00436       public Attributes getAttributes() {
            return getStartTag().getAttributes();
      }

      /**
       * Returns the {@linkplain CharacterReference#decode(CharSequence) decoded} value of the attribute with the specified name (case insensitive).
       * <p>
       * Returns <code>null</code> if the {@linkplain #getStartTag() start tag of this element} does not
       * {@linkplain StartTagType#hasAttributes() have attributes},
       * no attribute with the specified name exists or the attribute {@linkplain Attribute#hasValue() has no value}.
       * <p>
       * This is equivalent to {@link #getStartTag()}<code>.</code>{@link StartTag#getAttributeValue(String) getAttributeValue(attributeName)}.
       *
       * @param attributeName  the name of the attribute to get.
       * @return the {@linkplain CharacterReference#decode(CharSequence) decoded} value of the attribute with the specified name, or <code>null</code> if the attribute does not exist or {@linkplain Attribute#hasValue() has no value}.
       */
00452       public String getAttributeValue(final String attributeName) {
            return getStartTag().getAttributeValue(attributeName);
      }

      /**
       * Returns the {@link FormControl} defined by this element.
       * @return the {@link FormControl} defined by this element, or <code>null</code> if it is not a <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-controls">control</a>.
       */
00460       public FormControl getFormControl() {
            return FormControl.construct(this);
      }

00464       public String getDebugInfo() {
            if (this==NOT_CACHED) return "NOT_CACHED";
            final StringBuffer sb=new StringBuffer();
            sb.append("Element ").append(super.getDebugInfo()).append(": ");
            startTag.appendStartTagDebugInfo(sb);
            sb.append(endTag==null ? "(no end tag)" : "(with end tag)");
            return sb.toString();
      }

      /**
       * Returns the {@linkplain #getContent() content} text of the element.
       * <p>
       * This method has been deprecated as of version 2.0 as the {@link Segment} returned by the {@link #getContent()} method
       * now implements <code>CharSequence</code> and can be used directly in many cases.
       * Use {@link #getContent()}<code>.</code>{@link #toString() toString()} if a <code>String</code> is required.
       *
       * @return the content text of the element, or <code>null</code> if the element is {@linkplain #isEmpty() empty}.
       * @deprecated  Use {@link #isEmpty() isEmpty()}<code> ? null : </code>{@link #getContent()}<code>.</code>{@link #toString() toString()} instead.
       */
00483       public String getContentText() {
            return isEmpty() ? null : toString();
      }

      /**
       * Indicates whether the specified element name is an HTML {@linkplain HTMLElements#getBlockLevelElementNames() block-level element}.
       * <p>
       * This method has been deprecated as of version 2.0 as the {@link HTMLElements#getBlockLevelElementNames()} method now provides
       * a complete set of the element names for which this method returns <code>true</code>.
       *
       * @param elementName  an element {@linkplain #getName() name}.
       * @return <code>true</code> if the specified element name is an HTML {@linkplain HTMLElements#getBlockLevelElementNames() block-level element}, otherwise <code>false</code>.
       * @deprecated  Use {@link HTMLElements#getBlockLevelElementNames()}<code>.contains(elementName.toLowerCase())</code> instead.
       */
00497       public static boolean isBlock(final String elementName) {
            return HTMLElements.getBlockLevelElementNames().contains(elementName.toLowerCase());
      }

      /**
       * Indicates whether the specified element name is an HTML {@linkplain HTMLElements#getInlineLevelElementNames() inline-level element}.
       * <p>
       * This method has been deprecated as of version 2.0 as the {@link HTMLElements#getInlineLevelElementNames()} method now provides
       * a complete set of the element names for which this method returns <code>true</code>.
       *
       * @param elementName  an element {@linkplain #getName() name}.
       * @return <code>true</code> if the specified element name is an HTML {@linkplain HTMLElements#getInlineLevelElementNames() inline-level element}, otherwise <code>false</code>.
       * @deprecated  Use {@link HTMLElements#getInlineLevelElementNames()}<code>.contains(elementName.toLowerCase())</code> instead.
       */
00511       public static boolean isInline(final String elementName) {
            return HTMLElements.getInlineLevelElementNames().contains(elementName.toLowerCase());
      }

      int getContentEnd() {
            return endTag!=null ? endTag.begin : end;
      }
}


Generated by  Doxygen 1.6.0   Back to index