java - HTMLDocument 文本中位置或偏移量的含义

标签 java html swing

我试图了解位置/偏移量在 HTMLDocument 中的工作原理。描述了位置/偏移语义 here .我的解释是,这些是由 HTMLDocument 表示的屏幕字符序列中的索引。

考虑来自 the HTMLDocument documentation 的示例 HTML :

 <html>
   <head>
     <title>An example HTMLDocument</title>
     <style type="text/css">
       div { background-color: silver; }
       ul { color: red; }
     </style>
   </head>
   <body>
     <div id="BOX">
       <p>Paragraph 1</p>
       <p>Paragraph 2</p>
     </div>
   </body>
 </html>

当我在浏览器中打开此 HTML 时,我只看到“第 1 段”和“第 2 段”(没有前导空格或换行符)。所以我认为“第 1 段”从偏移 0 开始。

但请考虑以下代码,我在示例 HTML 中打印文本和主体的偏移量:

import java.io.StringReader;
import javax.swing.text.Element;
import javax.swing.text.html.*;

public class Test {
    public static void main(String[] args) throws Exception {
        String html = " <html>\n"
                    + "   <head>\n"
                    + "     <title>An example HTMLDocument</title>\n"
                    + "     <style type=\"text/css\">\n"
                    + "       div { background-color: silver; }\n"
                    + "       ul { color: red; }\n"
                    + "     </style>\n"
                    + "   </head>\n"
                    + "   <body>\n"
                    + "     <div id=\"BOX\">\n"
                    + "       <p>Paragraph 1</p>\n"
                    + "       <p>Paragraph 2</p>\n"
                    + "     </div>\n"
                    + "   </body>\n"
                    + " </html>\n";

        HTMLEditorKit htmlKit = new HTMLEditorKit();
        HTMLDocument doc = (HTMLDocument) htmlKit.createDefaultDocument();
        htmlKit.read(new StringReader(html), doc, 0);

        System.out.println("doc length: " + doc.getLength());
        String text = doc.getText(0, doc.getLength());
        System.out.println("doc text, surrounded by quotes, with newlines replaced with /: \""
                + text.replace('\n', '/') + "\"");

        Element element = doc.getDefaultRootElement().getElement(1);
        System.out.println("element name: " + element.getName());
        int offset = element.getStartOffset();
        System.out.println("offset of body: " + offset);
    }
}

输出:

doc length: 26
doc text, surrounded by quotes, with newlines replaced with /: "  /Paragraph 1/Paragraph 2"
element name: body
offset of body: 3

基本问题:为什么“Paragraph 1”(正文的开头)位于索引 3 处?文本的前三个字符(两个空格和一个换行符)来自哪里?我是否误解了“偏移量”的含义?

挑战问题:给定一些 HTML(简单到可以通过检查完全理解),我怎样才能严格地手工计算出所有 DOM 元素的偏移量?


更多信息:

如果我从 HTML 中删除 style 标签,我会得到相同的结果(3 的正文偏移量)。如果我还删除了 title,我得到的正文偏移量为​​ 1。如果我最终完全删除 head,我会得到 0 的正文偏移量(正如预期的那样)。那么显然 style 贡献了 0,title 贡献了 2,而 head 贡献了 1 到 body 的偏移量?这背后的原因是什么?

这似乎也不受 HTML 字符串中空格的影响。

最佳答案

好问题。您可以根据一些规则计算出偏移量(以及 JEditorPane 中必要的插入符位置)——您已经提到了最重要的规则。

也许有几个关键标签是:

  • <head> +1
  • <title> +2
  • <meta> +1
  • <p>文本长度 +1(对于 CR)

如果您还没有找到它,查看偏移量列表及其分解方式的最简单方法是 HTMLDocument.dump(System.out); .例如。对于上面的示例 HTML:

<html
  name=html
>
  <head
    name=head
  >
    <p-implied
      name=p-implied
    >
      <title
        name=title
      >
        [0,1][ ]
      <title
        endtag=true
        name=title
      >
        [1,2][ ]
      <content
        CR=true
        name=content
      >
        [2,3][
]
  <body
    name=body
  >
    <div
      id=BOX
      name=div
    >
      <p
        name=p
      >
        <content
          name=content
        >
          [3,14][Paragraph 1]
        <content
          CR=true
          name=content
        >
          [14,15][
]
      <p
        name=p
      >
        <content
          name=content
        >
          [15,26][Paragraph 2]
        <content
          CR=true
          name=content
        >
          [26,27][
]
<bidi root>
  <bidi level
    bidiLevel=0
  >
    [0,27][  
Paragraph 1
Paragraph 2
]

如果您有兴趣深入研究,这将意味着探索 Swing 解析逻辑中的 HTML 规则。不同标签类型有很多规则 - 您可以在 source 中查看列表.

每个标签在此层次结构中使用一个“Action”类:

swing-html-actions

例如<p>ParagraphAction , 和 <head>HeadAction , 而这两个都是 BlockAction 的类型. <div>也是直接一个BlockAction .

A BlockAction可以添加额外的 <content CR...>元素,以完成 block ,因此偏移量额外+1。它通常只有在标签中有直接文本内容时才会这样做。对于 <head>不过,HeadAction子类添加了 <p-implied>您可以在上面的转储中看到,这导致了一个额外的偏移量。 (您在本例中看不到它,但值得注意的是带有文本内容的 <div> 还会插入额外的 <p-implied> - 以保存 block 文本)。

事情从那里开始变得更加具体。例如。 <title> (连同 <applet><object> )似乎是“非空” HiddenActions .这意味着为开始和结束标记都插入了一个元素。 <meta>虽然,例如,是一个空的 HiddenAction , 因此只获取一个元素作为开始标记。

希望这足以解释如何计算任何给定标签的偏移量。如果浏览 XxxActions 的源代码类,寻找类似 new ElementSpec(..., 0, 1) 的行- 最后一个参数是长度。

您还提到空格被忽略。这至少在 HTML 解析中是正常的,在浏览器中也是如此。标签之间或文本前后的空白通常会被忽略——只保留单词之间的空白。然后,空格序列被折叠成一个空格。


总而言之,我仍然不清楚为什么 <head> 需要额外的偏移量和 <title> .例如。如果你使用 setCaretPosition(x)针对 JEditorPane基于 dochtmlKit在上面,如果 x,您只会看到插入符号是3个或更多。也许其他人可以阐明这一点......

关于java - HTMLDocument 文本中位置或偏移量的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50602095/

相关文章:

html - 为什么特定 div 元素的属性会传播到其他单独的 div 元素?

html - 给字段集的标题一个背景色

java - assertEquals 有问题

java - 找不到功能 'default' 的元工厂;这通常意味着 axiom-impl.jar 不在类路径中

html - Facebook 共享抓取工具未注册 al : tags

java:有什么方法可以检测显示配置的变化?

java - 使 JButton 在一个类中打开单独的 JDialog 类

java - 无法构建JBoss

java - 未找到 json-simple.jar

java - JToolbar 中 JButton 中的 AbstractAction 没有文本