⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 node.java

📁 windows 代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * @(#)Node.java   1.11 2000/08/16
 *
 */

package org.w3c.tidy;

/**
 *
 * Node
 *
 * (c) 1998-2000 (W3C) MIT, INRIA, Keio University
 * See Tidy.java for the copyright notice.
 * Derived from <a href="http://www.w3.org/People/Raggett/tidy">
 * HTML Tidy Release 4 Aug 2000</a>
 *
 * @author  Dave Raggett <dsr@w3.org>
 * @author  Andy Quick <ac.quick@sympatico.ca> (translation to Java)
 * @version 1.0, 1999/05/22
 * @version 1.0.1, 1999/05/29
 * @version 1.1, 1999/06/18 Java Bean
 * @version 1.2, 1999/07/10 Tidy Release 7 Jul 1999
 * @version 1.3, 1999/07/30 Tidy Release 26 Jul 1999
 * @version 1.4, 1999/09/04 DOM support
 * @version 1.5, 1999/10/23 Tidy Release 27 Sep 1999
 * @version 1.6, 1999/11/01 Tidy Release 22 Oct 1999
 * @version 1.7, 1999/12/06 Tidy Release 30 Nov 1999
 * @version 1.8, 2000/01/22 Tidy Release 13 Jan 2000
 * @version 1.9, 2000/06/03 Tidy Release 30 Apr 2000
 * @version 1.10, 2000/07/22 Tidy Release 8 Jul 2000
 * @version 1.11, 2000/08/16 Tidy Release 4 Aug 2000
 */

/*
  Used for elements and text nodes
  element name is null for text nodes
  start and end are offsets into lexbuf
  which contains the textual content of
  all elements in the parse tree.

  parent and content allow traversal
  of the parse tree in any direction.
  attributes are represented as a linked
  list of AttVal nodes which hold the
  strings for attribute/value pairs.
*/

public class Node {

    public static final short RootNode        = 0;
    public static final short DocTypeTag      = 1;
    public static final short CommentTag      = 2;
    public static final short ProcInsTag      = 3;
    public static final short TextNode        = 4;
    public static final short StartTag        = 5;
    public static final short EndTag          = 6;
    public static final short StartEndTag     = 7;
    public static final short CDATATag        = 8;
    public static final short SectionTag      = 9;
    public static final short AspTag          = 10;
    public static final short JsteTag         = 11;
    public static final short PhpTag          = 12;

    protected Node parent;
    protected Node prev;
    protected Node next;
    protected Node last;
    protected int start;             /* start of span onto text array */
    protected int end;               /* end of span onto text array */
    protected byte[] textarray;      /* the text array */
    protected short type;              /* TextNode, StartTag, EndTag etc. */
    protected boolean closed;            /* true if closed by explicit end tag */
    protected boolean implicit;          /* true if inferred */
    protected boolean linebreak;         /* true if followed by a line break */
    protected Dict was;   /* old tag when it was changed */
    protected Dict tag;   /* tag's dictionary definition */
    protected String element;          /* name (null for text nodes) */
    protected AttVal attributes;
    protected Node content;

    public Node()
    {
        this(TextNode, null, 0, 0);
    }

    public Node(short type, byte[] textarray, int start, int end)
    {
        this.parent = null;
        this.prev = null;
        this.next = null;
        this.last = null;
        this.start = start;
        this.end = end;
        this.textarray = textarray;
        this.type = type;
        this.closed = false;
        this.implicit = false;
        this.linebreak = false;
        this.was = null;
        this.tag = null;
        this.element = null;
        this.attributes = null;
        this.content = null;
    }

    public Node(short type, byte[] textarray, int start, int end, String element)
    {
        this.parent = null;
        this.prev = null;
        this.next = null;
        this.last = null;
        this.start = start;
        this.end = end;
        this.textarray = textarray;
        this.type = type;
        this.closed = false;
        this.implicit = false;
        this.linebreak = false;
        this.was = null;
        this.tag = null;
        this.element = element;
        this.attributes = null;
        this.content = null;
        if (type == StartTag || type == StartEndTag || type == EndTag)
            TagTable.getDefaultTagTable().findTag(this);
    }

    /* used to clone heading nodes when split by an <HR> */
    protected Object clone()
    {
        Node node = new Node();

        node.parent = this.parent;
        if (this.textarray != null)
        {
            node.textarray = new byte[this.end - this.start];
            node.start = 0;
            node.end = this.end - this.start;
            if (node.end > 0)
                System.arraycopy(this.textarray, this.start,
                                 node.textarray, node.start, node.end);
        }
        node.type = this.type;
        node.closed = this.closed;
        node.implicit = this.implicit;
        node.linebreak = this.linebreak;
        node.was = this.was;
        node.tag = this.tag;
        if (this.element != null)
            node.element = new String(this.element);
        if (this.attributes != null)
            node.attributes = (AttVal)this.attributes.clone();
        return node;
    }

    public AttVal getAttrByName(String name)
    {
        AttVal attr;

        for (attr = this.attributes; attr != null; attr = attr.next)
        {
            if (name != null &&
                attr.attribute != null &&
                attr.attribute.equals(name))
                break;
        }

        return attr;
    }

    /* default method for checking an element's attributes */
    public void checkAttributes( Lexer lexer )
    {
        AttVal attval;

        for (attval = this.attributes; attval != null; attval = attval.next)
            attval.checkAttribute( lexer, this );
    }

    public void checkUniqueAttributes(Lexer lexer)
    {
        AttVal attval;

        for (attval = this.attributes; attval != null; attval = attval.next) {
            if (attval.asp == null && attval.php == null)
                attval.checkUniqueAttribute(lexer, this);
        }
    }

    public void addAttribute(String name, String value)
    {
        AttVal av = new AttVal(null, null, null, null,
                               '"', new String(name), new String(value));
        av.dict =
          AttributeTable.getDefaultAttributeTable().findAttribute(av);

        if (this.attributes == null)
            this.attributes = av;
        else /* append to end of attributes */
        {
            AttVal here = this.attributes;

            while (here.next != null)
                here = here.next;

            here.next = av;
        }
    }

    /* remove attribute from node then free it */
    public void removeAttribute(AttVal attr)
    {
        AttVal av;
        AttVal prev = null;
        AttVal next;

        for (av = this.attributes; av != null; av = next)
        {
            next = av.next;

            if (av == attr)
            {
                if (prev != null)
                    prev.next = next;
                else
                    this.attributes = next;
            }
            else
                prev = av;
	}
    }

    /* find doctype element */
    public Node findDocType()
    {
        Node node;

        for (node = this.content; 
            node != null && node.type != DocTypeTag; node = node.next);

        return node;
    }

    public void discardDocType()
    {
        Node node;

        node = findDocType();
        if (node != null)
        {
            if (node.prev != null)
                node.prev.next = node.next;
            else
                node.parent.content = node.next;

            if (node.next != null)
                node.next.prev = node.prev;

            node.next = null;
        }
    }

    /* remove node from markup tree and discard it */
    public static Node discardElement(Node element)
    {
        Node next = null;

        if (element != null)
        {
            next = element.next;
            removeNode(element);
        }

        return next;
    }

    /* insert node into markup tree */
    public static void insertNodeAtStart(Node element, Node node)
    {
        node.parent = element;

        if (element.content == null)
            element.last = node;
        else
            element.content.prev = node; // AQ added 13 Apr 2000

        node.next = element.content;
        node.prev = null;
        element.content = node;
    }

    /* insert node into markup tree */
    public static void insertNodeAtEnd(Node element, Node node)
    {
        node.parent = element;
        node.prev = element.last;

        if (element.last != null)
            element.last.next = node;
        else
            element.content = node;

        element.last = node;
    }

    /*
     insert node into markup tree in pace of element
     which is moved to become the child of the node
    */
    public static void insertNodeAsParent(Node element, Node node)
    {
        node.content = element;
        node.last = element;
        node.parent = element.parent;
        element.parent = node;
    
        if (node.parent.content == element)
            node.parent.content = node;

        if (node.parent.last == element)
            node.parent.last = node;

        node.prev = element.prev;
        element.prev = null;

        if (node.prev != null)
            node.prev.next = node;

        node.next = element.next;
        element.next = null;

        if (node.next != null)
            node.next.prev = node;
    }

    /* insert node into markup tree before element */
    public static void insertNodeBeforeElement(Node element, Node node)
    {
        Node parent;

        parent = element.parent;
        node.parent = parent;
        node.next = element;
        node.prev = element.prev;
        element.prev = node;

        if (node.prev != null)
            node.prev.next = node;

        if (parent.content == element)
            parent.content = node;
    }

    /* insert node into markup tree after element */
    public static void insertNodeAfterElement(Node element, Node node)
    {
        Node parent;

        parent = element.parent;
        node.parent = parent;

        // AQ - 13Jan2000 fix for parent == null
        if (parent != null && parent.last == element)
            parent.last = node;
        else
        {
            node.next = element.next;
            // AQ - 13Jan2000 fix for node.next == null
            if (node.next != null)
                node.next.prev = node;
        }

        element.next = node;
        node.prev = element;
    }

    public static void trimEmptyElement(Lexer lexer, Node element)
    {
        if (lexer.canPrune(element))
        {
            if (element.type != TextNode)
                Report.warning(lexer, element, null, Report.TRIM_EMPTY_ELEMENT);

            discardElement(element);
        }
        else if (element.tag == TagTable.tagP && element.content == null)
        {
            /* replace <p></p> by <br><br> to preserve formatting */
            Node node = lexer.inferredTag("br");
            Node.coerceNode(lexer, element, TagTable.tagBr);
            Node.insertNodeAfterElement(element, node);
        }
    }

    /*
      This maps 
           <em>hello </em><strong>world</strong>
      to
           <em>hello</em> <strong>world</strong>

      If last child of element is a text node
      then trim trailing white space character
      moving it to after element's end tag.
    */
    public static void trimTrailingSpace(Lexer lexer, Node element, Node last)
    {
        byte c;

        if (last != null && last.type == Node.TextNode &&
            last.end > last.start)
        {
            c = lexer.lexbuf[last.end - 1];

            if (c == 160 || c == (byte)' ')
            {
                /* take care with <td>&nbsp;</td> */
                if (element.tag == TagTable.tagTd ||
                    element.tag == TagTable.tagTh)
                {
                    if (last.end > last.start + 1)
                        last.end -= 1;
                }
                else
                {
                    last.end -= 1;

                    if (((element.tag.model & Dict.CM_INLINE) != 0) &&
                            !((element.tag.model & Dict.CM_FIELD) != 0))
                        lexer.insertspace = true;

                    /* if empty string then delete from parse tree */
                    if (last.start == last.end)
                        trimEmptyElement(lexer, last);
                }
            }
        }
    }

    /*
      This maps 
           <p>hello<em> world</em>
      to
           <p>hello <em>world</em>

      Trims initial space, by moving it before the
      start tag, or if this element is the first in
      parent's content, then by discarding the space
    */
    public static void trimInitialSpace(Lexer lexer, Node element, Node text)
    {
        Node prev, node;

        // GLP: Local fix to Bug 119789. Remove this comment when parser.c is updated.
        //      31-Oct-00. 
        if (text.type == TextNode && text.textarray[text.start] == (byte)' ' 
                           && (text.start < text.end))
        {
            if (((element.tag.model & Dict.CM_INLINE) != 0) &&
                !((element.tag.model & Dict.CM_FIELD) != 0) &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -