Module java.desktop

Class HTMLDocument

所有已实现的接口:
Serializable, Document, StyledDocument

public class HTMLDocument extends DefaultStyledDocument
一个模拟HTML的文档。此模型的目的是支持浏览和编辑。因此,默认情况下,HTML文档描述的结构并不完全复制。默认建模的元素结构是由类HTMLDocument.HTMLReader构建的,该类实现了解析器期望的HTMLEditorKit.ParserCallback协议。要更改结构,可以子类化HTMLReader,并重新实现方法getReader(int)以返回新的读取器实现。应查阅HTMLReader的文档以获取创建的默认结构的详细信息。目的是使文档非丢失(尽管重新生成HTML格式可能会导致不同的格式)。

文档仅模拟HTML,并不尝试在其中存储视图属性。元素由StyleContext.NameAttribute属性标识,该属性应始终具有HTML.Tag类型的值,以标识元素的类型。一些元素(如注释)是合成的。HTMLFactory使用此属性确定要构建的视图类型。

此文档支持增量加载。TokenThreshold属性控制在尝试更新文档的元素结构之前缓冲的解析量。此属性由EditorKit设置,以便子类可以禁用它。

Base属性确定相对URL解析的URL。默认情况下,这将是Document.StreamDescriptionProperty,如果属性的值是URL。如果遇到<BASE>标签,则基本URL将变为该标签指定的URL。因为基本URL是一个属性,所以当然可以直接设置。

此文档的默认内容存储机制是间隙缓冲区(GapContent)。可以通过使用接受Content实现的构造函数提供替代方案。

修改HTMLDocument

除了Document和StyledDocument提供的用于改变HTMLDocument的方法外,HTMLDocument还提供了许多便利方法。以下方法可用于将HTML内容插入现有文档中。

以下示例说明了如何使用这些方法。每个示例假定HTML文档是以以下方式初始化的:

 JEditorPane p = new JEditorPane();
 p.setContentType("text/html");
 p.setText("..."); // 文档文本在下面提供。
 HTMLDocument d = (HTMLDocument) p.getDocument();
 

使用以下HTML内容:

 <html>
   <head>
     <title>一个示例HTMLDocument</title>
     <style type="text/css">
       div { background-color: silver; }
       ul { color: blue; }
     </style>
   </head>
   <body>
     <div id="BOX">
       <p>段落 1</p>
       <p>段落 2</p>
     </div>
   </body>
 </html>
 

修改HTML文档的所有方法都需要一个Element。可以通过使用方法getElement(Element e, Object attribute, Object value)从HTML文档中获取元素。它以深度优先顺序返回包含指定属性及给定值的第一个后代元素。例如,d.getElement(d.getDefaultRootElement(), StyleConstants.NameAttribute, HTML.Tag.P)返回第一个段落元素。

定位元素的一个便捷快捷方式是方法getElement(String);返回一个其ID属性与指定值匹配的元素。例如,d.getElement("BOX")返回DIV元素。

方法getIterator(HTML.Tag t)也可用于在文档中查找指定HTML标记的所有出现。

插入元素

可以使用insertAfterStartinsertBeforeEnd方法在任何非叶元素的现有子元素之前或之后插入元素。例如,如果eDIV元素,则d.insertAfterStart(e, "<ul><li>列表项</li></ul>")在第一个段落之前插入列表,d.insertBeforeEnd(e, "<ul><li>列表项</li></ul>")在最后一个段落之后插入列表。新插入的元素的父元素为DIV块。

可以使用insertBeforeStartinsertAfterEnd方法在任何元素之前或之后插入同级元素。例如,如果eDIV元素,则d.insertBeforeStart(e, "<ul><li>列表项</li></ul>")DIV元素之前插入列表,d.insertAfterEnd(e, "<ul><li>列表项</li></ul>")DIV元素之后插入列表。新插入的元素成为DIV元素的同级元素。

替换元素

可以使用setInnerHTMLsetOuterHTML方法替换元素及其所有后代。例如,如果eDIV元素,则d.setInnerHTML(e, "<ul><li>列表项</li></ul>")用列表替换所有子段落,d.setOuterHTML(e, "<ul><li>列表项</li></ul>")替换DIV元素本身。在后一种情况下,列表的父元素是BODY元素。

总结

以下表格显示了上述示例文档和各种方法的结果。

上述示例的HTML内容
示例 insertAfterStart insertBeforeEnd insertBeforeStart insertAfterEnd setInnerHTML setOuterHTML

段落 1

段落 2

  • 列表项

段落 1

段落 2

段落 1

段落 2

  • 列表项
  • 列表项

段落 1

段落 2

段落 1

段落 2

  • 列表项
  • 列表项
  • 列表项

警告: 此类的序列化对象将不兼容未来的Swing版本。当前的序列化支持适用于短期存储或在运行相同Swing版本的应用程序之间的RMI。从1.4版本开始,已将所有JavaBeans的长期存储支持添加到java.beans包中。请参阅XMLEncoder

  • Field Details

    • AdditionalComments

      public static final String AdditionalComments
      文档属性键值。键的值将是一个字符串向量,其中包含在正文中未找到的注释。
      参见:
  • Constructor Details

    • HTMLDocument

      public HTMLDocument()
      使用默认缓冲区大小和默认StyleSheet构造HTML文档。这是构造函数HTMLDocument(Content, StyleSheet)的便利方法。
    • HTMLDocument

      public HTMLDocument(StyleSheet styles)
      使用默认内容存储实现和指定的样式/属性存储机制构造HTML文档。这是构造函数HTMLDocument(Content, StyleSheet)的便利方法。
      参数:
      styles - 样式
    • HTMLDocument

      public HTMLDocument(AbstractDocument.Content c, StyleSheet styles)
      使用给定的内容存储实现和给定的样式/属性存储机制构造HTML文档。
      参数:
      c - 内容的容器
      styles - 样式
  • Method Details

    • getReader

      public HTMLEditorKit.ParserCallback getReader(int pos)
      获取解析器在加载包含HTML的文档时使用的阅读器。这是实现为返回HTMLDocument.HTMLReader实例。子类可以重新实现此方法以根据需要更改文档的结构(例如,处理自定义标签或结构上代表字符样式元素)。
      参数:
      pos - 起始位置
      返回:
      解析器用于加载文档的阅读器
    • getReader

      public HTMLEditorKit.ParserCallback getReader(int pos, int popDepth, int pushDepth, HTML.Tag insertTag)
      返回解析器用于加载包含HTML的文档时使用的阅读器。这是实现为返回HTMLDocument.HTMLReader实例。子类可以重新实现此方法以根据需要更改文档的结构(例如,处理自定义标签或结构上代表字符样式元素)。

      这是getReader(int, int, int, HTML.Tag, TRUE)的便利方法。

      参数:
      pos - 起始位置
      popDepth - 在插入之前生成的ElementSpec.EndTagTypes数量
      pushDepth - 在生成结束标记后但在生成结束标记之前生成的具有ElementSpec.JoinNextDirection方向的ElementSpec.StartTagTypes数量
      insertTag - 要开始插入到文档中的第一个标记
      返回:
      解析器用于加载文档的阅读器
    • getBase

      public URL getBase()
      返回用于解析相对URL的位置。默认情况下,如果文档是从URL加载的,则这将是文档的URL。如果找到并且可以解析基本标记,则将使用其作为基本位置。
      返回:
      基本位置
    • setBase

      public void setBase(URL u)
      设置用于解析相对URL的位置。默认情况下,如果文档是从URL加载的,则这将是文档的URL。如果找到并且可以解析基本标记,则将使用其作为基本位置。

      这还将设置StyleSheet的基础为u,以及文档的基础。

      参数:
      u - 所需的基本URL
    • insert

      protected void insert(int offset, DefaultStyledDocument.ElementSpec[] data) throws BadLocationException
      批量插入新元素。这是文档中创建元素的方式。解析确定所需的结构并创建规范,作为描述编辑的一组标记,同时使文档不受写锁定。然后,阅读器可以以突发方式调用此方法,以获取更短时间的写锁定(即,在实际更改文档时)。
      覆盖:
      insert 在类中 DefaultStyledDocument
      参数:
      offset - 起始偏移量
      data - 元素数据
      抛出:
      BadLocationException - 如果给定位置不代表关联文档中的有效位置。
    • insertUpdate

      protected void insertUpdate(AbstractDocument.DefaultDocumentEvent chng, AttributeSet attr)
      作为文本插入的结果更新文档结构。这将在写锁定内发生。此实现简单地解析插入的内容以查找换行符,并构建一组元素缓冲区的指令。
      覆盖:
      insertUpdate 在类中 DefaultStyledDocument
      参数:
      chng - 文档更改的描述
      attr - 属性
    • create

      protected void create(DefaultStyledDocument.ElementSpec[] data)
      用给定的元素规范替换文档的内容。如果加载是分批进行的,则在插入之前调用此方法。如果完全在一个突发中加载文档,则只调用此方法。
      覆盖:
      create 在类中 DefaultStyledDocument
      参数:
      data - 文档的新内容
    • setParagraphAttributes

      public void setParagraphAttributes(int offset, int length, AttributeSet s, boolean replace)
      为段落设置属性。

      此方法是线程安全的,尽管大多数Swing方法不是。有关更多信息,请参阅Swing中的并发性

      指定者:
      setParagraphAttributes 在接口中 StyledDocument
      覆盖:
      setParagraphAttributes 在类中 DefaultStyledDocument
      参数:
      offset - 段落中的偏移量(必须至少为0)
      length - 受影响的字符数(必须至少为0)
      s - 属性
      replace - 是否替换现有属性或合并它们
    • getStyleSheet

      public StyleSheet getStyleSheet()
      获取在HTML文档本身中指定的文档特定显示规则(CSS)的StyleSheet
      返回:
      StyleSheet
    • getIterator

      public HTMLDocument.Iterator getIterator(HTML.Tag t)
      获取指定HTML标记的迭代器。这可用于遍历包含的锚点集或遍历输入元素。
      参数:
      t - 请求的HTML.Tag
      返回:
      给定HTML标记的Iterator
      参见:
    • createLeafElement

      protected Element createLeafElement(Element parent, AttributeSet a, int p0, int p1)
      创建直接表示文本的文档叶元素(没有任何子元素)。这是实现为返回类型为HTMLDocument.RunElement的元素。
      覆盖:
      createLeafElement 在类中 AbstractDocument
      参数:
      parent - 父元素
      a - 元素的属性
      p0 - 范围的开始(必须至少为0)
      p1 - 范围的结束(必须至少为p0)
      返回:
      新元素
    • createBranchElement

      protected Element createBranchElement(Element parent, AttributeSet a)
      创建可以包含其他元素的文档分支元素。这是实现为返回类型为HTMLDocument.BlockElement的元素。
      覆盖:
      createBranchElement 在类 AbstractDocument
      参数:
      parent - 父元素
      a - 属性
      返回:
      元素
    • createDefaultRoot

      protected AbstractDocument.AbstractElement createDefaultRoot()
      创建用于表示默认文档结构的根元素。
      覆盖:
      createDefaultRoot 在类 DefaultStyledDocument
      返回:
      基本元素
    • setTokenThreshold

      public void setTokenThreshold(int n)
      设置在尝试更新文档元素结构之前要缓冲的令牌数。
      参数:
      n - 要缓冲的令牌数
    • getTokenThreshold

      public int getTokenThreshold()
      获取在尝试更新文档元素结构之前要缓冲的令牌数。默认值为Integer.MAX_VALUE
      返回:
      要缓冲的令牌数
    • setPreservesUnknownTags

      public void setPreservesUnknownTags(boolean preservesTags)
      确定解析器如何处理未知标记。如果设置为true,则未知标记将放入模型中,否则它们将被丢弃。
      参数:
      preservesTags - 如果应保存未知标记,则为true,否则标记将被丢弃
      参见:
    • getPreservesUnknownTags

      public boolean getPreservesUnknownTags()
      返回解析器在遇到未知标记时遵循的行为。
      返回:
      如果解析时应保留未知标记,则为true
      参见:
    • processHTMLFrameHyperlinkEvent

      public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent e)
      处理由HTML框架中的文档生成的HyperlinkEvents。正如参数所示,HyperlinkEvent类型是HTMLFrameHyperlinkEvent。除了HyperlinkEvent中包含的典型信息外,此事件还包含与发生点击的框架对应的元素(源元素)和目标名称。目标名称有4个可能的值:
      • _self
      • _parent
      • _top
      • 命名的框架
      如果目标是_self,则操作是更改HTML.Attribute.SRC属性的值并触发ChangedUpdate事件。

      如果目标是_parent,则删除父元素(一个<FRAMESET>元素),并插入一个新的<FRAME>元素,并将其HTML.Attribute.SRC属性设置为与目标URL相等的值,并触发RemovedUpdateInsertUpdate事件。

      如果目标是_top,则此方法不执行任何操作。在框架的视图实现中,即FrameView,处理_top的处理。鉴于_top意味着替换整个文档,将其处理在将要替换的文档之外是有意义的。

      如果目标是命名的框架,则会搜索元素层次结构,查找名称等于目标的元素,更新其HTML.Attribute.SRC属性,并触发ChangedUpdate事件。

      参数:
      e - 事件
    • setParser

      public void setParser(HTMLEditorKit.Parser parser)
      设置用于将HTML插入现有文档的方法使用的解析器,例如setInnerHTMLsetOuterHTML

      HTMLEditorKit.createDefaultDocument将为您设置解析器。如果手动创建HTMLDocument,请确保相应地设置解析器。

      参数:
      parser - 用于文本插入的解析器
      自:
      1.3
    • getParser

      public HTMLEditorKit.Parser getParser()
      返回在将HTML插入现有文档时使用的解析器。
      返回:
      用于文本插入的解析器
      自:
      1.3
    • setInnerHTML

      public void setInnerHTML(Element elem, String htmlText) throws BadLocationException, IOException
      用指定的HTML字符串替换给定元素的子元素。

      这将被视为至少两个事件,n次插入,然后是一个删除。

      考虑以下结构(elem参数用粗体表示)。

           <body>
             |
           <div>
            /  \
          <p>   <p>
       

      调用setInnerHTML(elem, "<ul><li>")将导致以下结构(新元素用蓝色表示)。

           <body>
             |
           <div>
               \
               <ul>
                 \
                 <li>
       

      参数elem不能是叶子元素,否则将抛出IllegalArgumentException。如果elemhtmlText参数为null,则不会对文档进行任何更改。

      为了使其正常工作,文档必须设置一个HTMLEditorKit.Parser。如果文档是通过createDefaultDocument方法从HTMLEditorKit创建的,则会出现这种情况。

      参数:
      elem - 将要替换其子元素的分支元素
      htmlText - 要解析并分配给elem的字符串
      抛出:
      IllegalArgumentException - 如果elem是叶子
      IllegalStateException - 如果未定义HTMLEditorKit.Parser
      BadLocationException - 如果由于结构问题而无法进行替换
      IOException - 如果发生I/O异常
      自:
      1.3
    • setOuterHTML

      public void setOuterHTML(Element elem, String htmlText) throws BadLocationException, IOException
      用指定的HTML字符串替换父元素中给定的元素。

      这将被视为至少两个事件,n次插入,然后是一个删除。

      当替换叶子时,将尝试确保存在换行符(如果需要)。这可能导致插入额外元素。例如,如果您尝试用<img>替换包含换行符的字符元素,则会创建两个元素,一个用于图像,另一个用于换行符。

      如果尝试替换长度的元素,则最有可能会得到两个元素,例如setOuterHTML(getCharacterElement(getLength()), "blah")将在末尾产生两个叶子元素,一个表示'blah',另一个表示结束元素。

      考虑以下结构(elem参数用粗体表示)。

           <body>
             |
           <div>
            /  \
          <p>   <p>
       

      调用setOuterHTML(elem, "<ul><li>")将导致以下结构(新元素用蓝色表示)。

          <body>
            |
           <ul>
             \
             <li>
       

      如果elemhtmlText参数为null,则不会对文档进行任何更改。

      为了使其正常工作,文档必须设置一个HTMLEditorKit.Parser。如果文档是通过createDefaultDocument方法从HTMLEditorKit创建的,则会出现这种情况。

      参数:
      elem - 要替换的元素
      htmlText - 要解析并插入到elem位置的字符串
      抛出:
      IllegalStateException - 如果未设置HTMLEditorKit.Parser
      BadLocationException - 如果由于结构问题而无法进行替换
      IOException - 如果发生I/O异常
      自:
      1.3
    • insertAfterStart

      public void insertAfterStart(Element elem, String htmlText) throws BadLocationException, IOException
      在元素的开头插入指定的HTML字符串。

      考虑以下结构(elem参数用粗体表示)。

           <body>
             |
           <div>
            /  \
          <p>   <p>
       

      调用insertAfterStart(elem, "<ul><li>")将导致以下结构(新元素用蓝色表示)。

              <body>
                |
              <div>
             /  |  \
          <ul> <p> <p>
           /
        <li>
       

      insertBeforeStart方法不同,新元素成为指定元素的子元素,而不是同级元素。

      参数elem不能是叶子元素,否则将抛出IllegalArgumentException。如果elemhtmlText参数为null,则不会对文档进行任何更改。

      为了使其正常工作,文档必须设置一个HTMLEditorKit.Parser。如果文档是通过createDefaultDocument方法从HTMLEditorKit创建的,则会出现这种情况。

      参数:
      elem - 要成为新文本根的分支元素
      htmlText - 要解析并分配给elem的字符串
      抛出:
      IllegalArgumentException - 如果elem是叶子
      IllegalStateException - 如果文档上没有设置HTMLEditorKit.Parser
      BadLocationException - 如果由于结构问题而无法插入
      IOException - 如果发生I/O异常
      自1.3版本起:
      1.3
    • insertBeforeEnd

      public void insertBeforeEnd(Element elem, String htmlText) throws BadLocationException, IOException
      在元素末尾插入指定的HTML字符串。

      如果elem的子元素是叶子,并且elem.getEndOffset() - 1处的字符是换行符,则会在换行符之前插入,以确保换行符后没有文本。

      考虑以下结构(elem参数用粗体表示)。

           <body>
             |
           <div>
            /  \
          <p>   <p>
       

      调用insertBeforeEnd(elem, "<ul><li>")将导致以下结构(新元素以蓝色表示)。

              <body>
                |
              <div>
             /  |  \
           <p> <p> <ul>
                     \
                     <li>
       

      insertAfterEnd方法不同,新元素成为指定元素的子元素,而不是兄弟元素。

      参数elem不能是叶子元素,否则将抛出IllegalArgumentException。如果elemhtmlText参数为null,则不会对文档进行任何更改。

      为使其正常工作,文档必须设置HTMLEditorKit.Parser。如果文档是通过createDefaultDocument方法从HTMLEditorKit创建的,则会出现这种情况。

      参数:
      elem - 要成为新文本根的元素
      htmlText - 要解析并分配给elem的字符串
      抛出:
      IllegalArgumentException - 如果elem是叶子
      IllegalStateException - 如果文档上没有设置HTMLEditorKit.Parser
      BadLocationException - 如果由于结构问题而无法插入
      IOException - 如果发生I/O异常
      自1.3版本起:
      1.3
    • insertBeforeStart

      public void insertBeforeStart(Element elem, String htmlText) throws BadLocationException, IOException
      在给定元素的开头之前插入指定的HTML字符串。

      考虑以下结构(elem参数用粗体表示)。

           <body>
             |
           <div>
            /  \
          <p>   <p>
       

      调用insertBeforeStart(elem, "<ul><li>")将导致以下结构(新元素以蓝色表示)。

              <body>
               /  \
            <ul> <div>
             /    /  \
           <li> <p>  <p>
       

      insertAfterStart方法不同,新元素成为指定元素的兄弟元素,而不是子元素。

      如果elemhtmlText参数为null,则不会对文档进行任何更改。

      为使其正常工作,文档必须设置HTMLEditorKit.Parser。如果文档是通过createDefaultDocument方法从HTMLEditorKit创建的,则会出现这种情况。

      参数:
      elem - 要在其之前插入内容的元素
      htmlText - 要解析并在elem之前插入的字符串
      抛出:
      IllegalStateException - 如果文档上没有设置HTMLEditorKit.Parser
      BadLocationException - 如果由于结构问题而无法插入
      IOException - 如果发生I/O异常
      自1.3版本起:
      1.3
    • insertAfterEnd

      public void insertAfterEnd(Element elem, String htmlText) throws BadLocationException, IOException
      在给定元素的末尾之后插入指定的HTML字符串。

      考虑以下结构(elem参数用粗体表示)。

           <body>
             |
           <div>
            /  \
          <p>   <p>
       

      调用insertAfterEnd(elem, "<ul><li>")将导致以下结构(新元素以蓝色表示)。

              <body>
               /  \
            <div> <ul>
             / \    \
           <p> <p>  <li>
       

      insertBeforeEnd方法不同,新元素成为指定元素的兄弟元素,而不是子元素。

      如果elemhtmlText参数为null,则不会对文档进行任何更改。

      为使其正常工作,文档必须设置HTMLEditorKit.Parser。如果文档是通过createDefaultDocument方法从HTMLEditorKit创建的,则会出现这种情况。

      参数:
      elem - 要在其之后插入内容的元素
      htmlText - 要解析并在elem之后插入的字符串
      抛出:
      IllegalStateException - 如果文档上没有设置HTMLEditorKit.Parser
      BadLocationException - 如果由于结构问题而无法插入
      IOException - 如果发生I/O异常
      自1.3版本起:
      1.3
    • getElement

      public Element getElement(String id)
      返回具有给定id Attribute的元素。如果找不到元素,则返回null。请注意,此方法适用于Attribute,而不是字符标签。在以下HTML片段中:<a id="HelloThere">,属性是'id',字符标签是'a'。这是getElement(RootElement, HTML.Attribute.id, id)的便利方法。此方法不是线程安全的。
      参数:
      id - 表示所需Attribute的字符串
      返回:
      具有指定Attribute的元素,如果找不到则返回null,如果idnull则返回null
      自1.3版本起:
      1.3
      参见:
    • getElement

      public Element getElement(Element e, Object attribute, Object value)
      返回包含属性attribute值为valuee的子元素,如果找不到则返回null。此方法不是线程安全的。
      参数:
      e - 开始搜索的根元素
      attribute - 所需的Attribute
      value - 指定Attribute的值
      返回:
      具有指定Attribute和指定value的元素,如果找不到则返回null
      自1.3版本起:
      1.3
      参见:
    • fireChangedUpdate

      protected void fireChangedUpdate(DocumentEvent e)
      通知所有已注册对此事件类型感兴趣的侦听器。事件实例是使用传递给fire方法的参数延迟创建的。
      覆盖:
      fireChangedUpdate 在类 AbstractDocument
      参数:
      e - 事件
      参见:
    • fireUndoableEditUpdate

      protected void fireUndoableEditUpdate(UndoableEditEvent e)
      通知所有已注册对此事件类型感兴趣的侦听器。事件实例是使用传递给fire方法的参数延迟创建的。
      覆盖:
      fireUndoableEditUpdate 在类 AbstractDocument
      参数:
      e - 事件
      参见: