在Golang中提取* html.Node的位置偏移量

时间:2016-01-15 13:34:28

标签: html go

如何为已解析的HTML文档的特定节点提取位置偏移量?例如,对于文档<div>Hello, <b>World!</b></div>,我希望能够知道World!的偏移量为15:21。解析时可能会更改文档。

我有一个解决方案来渲染带有特殊标记的整个文档,但这对性能来说非常糟糕。有什么想法吗?

package main

import (
    "bytes"
    "golang.org/x/net/html"
    "golang.org/x/net/html/atom"
    "log"
    "strings"
)

func nodeIndexOffset(context *html.Node, node *html.Node) (int, int) {
    if node.Type != html.TextNode {
        node = node.FirstChild
    }
    originalData := node.Data

    var buf bytes.Buffer
    node.Data = "|start|" + originalData
    _ = html.Render(&buf, context.FirstChild)
    start := strings.Index(buf.String(), "|start|")

    buf = bytes.Buffer{}
    node.Data = originalData + "|end|"
    _ = html.Render(&buf, context.FirstChild)
    end := strings.Index(buf.String(), "|end|")

    node.Data = originalData
    return start, end
}

func main() {
    s := "<div>Hello, <b>World!</b></div>"
    var context html.Node
    context = html.Node{
        Type:     html.ElementNode,
        Data:     "body",
        DataAtom: atom.Body,
    }
    nodes, err := html.ParseFragment(strings.NewReader(s), &context)
    if err != nil {
        log.Fatal(err)
    }
    for _, node := range nodes {
        context.AppendChild(node)
    }
    world := nodes[0].FirstChild.NextSibling.FirstChild
    log.Println("target", world)
    log.Println(nodeIndexOffset(&context, world))
}

2 个答案:

答案 0 :(得分:3)

不是答案,但评论时间太长。以下可能在某种程度上起作用:

  • 使用Tokenizer逐个逐步浏览每个元素。
  • 将您的输入内容传输到自定义阅读器中,该阅读器会记录行和 Tokenizer从中读取列偏移量。
  • 在调用Next()之前和之后查询自定义阅读器的位置 记录您需要的大致位置信息。

这有点痛苦,而且准确,但可能是你能做到的最好。

答案 1 :(得分:0)

我想出了我们扩展的解决方案(如果还有其他方法,请修复我)原始HTML包以及带有新导出功能的附加$('#retailer_stock').click(function(e){ $(this).parent().find('[data-name="rid"]').text() });文件。此函数可以访问custom.go的未导出data属性,该属性保存当前Tokenizer的开始和结束位置。我们必须在每次读取缓冲区后调整位置。请参阅Node

我真的不喜欢我只需要将包分叉来访问几个属性,但看起来这是一个Go方式。

globalBufDif