Golang中如何向head标签插入多个标签

Golang中如何向head标签插入多个标签 我已经对 net/html 库进行了大量尝试,并且已经能够修改每个 “img” 标签的 “src” 属性以指向不同的图像。然而,我在这里遇到了一点困难,因为我正在尝试做一些更复杂的事情。我需要将一些 HTML 插入到一个已存在的 head 标签中。我需要插入的内容看起来像这样:

<![CDATA[
<script type="text/javascript">
var continentCode="EU";
var doComplianceCheck=true;
</script>
<script src="/another.js"></script>
<script src="path/to/some.js"></script>]]>

有没有一种简单的方法可以将它插入到 head 标签中? 提前感谢您的任何帮助。


更多关于Golang中如何向head标签插入多个标签的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

我对这段代码有点困惑。你能解释一下各个变量的作用吗?另外,我对 ExecuteTemplate 的具体工作原理也不太清楚。如何指定要将 HTML 插入到 pagebuf 的哪个部分?我需要将内容追加到 HEAD 标签中已有的内容之后。

更多关于Golang中如何向head标签插入多个标签的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


啊,好的,我现在明白你的意思了。问题是,我想要注入代码的HTML不是一个模板。它是一个来自Web服务器的HTML页面。所以,在那个HTML里没有任何像“在此处插入”这样的标记,或者你在模板里会有的那种东西。我只需要在从Web服务器接收到这个HTML时,将我的代码片段追加到HEAD标签里。

如何指定您想将HTML插入到pagebuf的哪个部分?

有三个部分:

  1. 页面(主页面)
  2. 占位符(插入位置)
  3. 注入内容(要插入的内容)

Go Playground - The Go Programming Language

ExecuteTemplate 具体是如何工作的。

通常,您将整个渲染后的模板发送到 http.ResponseWriter(您的网站)。

tpl.ExecuteTemplate(w, page, nil)

或者,将其保留在内存(缓冲区)中,直到您将HTML直接写入客户端,因为无需重新渲染组合后的HTML。

w.Write(combined_buf)

但正如我之前所说,还有其他更简单的方法来实现这一点,例如使用JavaScript,或者通过向模板传递参数来注入内容。

{{.}}

有没有简单的方法把它塞进 head 标签里?

最简单的方法是使用 JavaScript 将新代码添加到 innerHTML。

不那么简单但有点类似“Go 版 innerHTML”的方法是,将两者都渲染到缓冲区,然后将它们组合成一个新页面。伪代码如下:

var tpl *template.Template
var hdrbuf bytes.Buffer
var pagebuf bytes.Buffer

func main() {
	insert := `<div>injected header</div>`
	page := `<body><!-- PLACEHOLDER --></body>`

	tpl.ExecuteTemplate(&pagebuf, page, nil)
	tpl.ExecuteTemplate(&insert, page, nil)
	combined_buf := add_hdr2page()
	fmt.Println(combined_buf)

	// test
	fmt.Println(string(new_page))

}

// add header to every page
func add_hdr2page() []byte {
	placeholder := []byte(`<!-- PLACEHOLDER -->`)
	combined_buf := bytes.ReplaceAll(pagebuf.Bytes(), placeholder, hdrbuf.Bytes())
	return combined_buf
}

我最终使用了 goQuery,方法如下:

		bytes, err := io.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("Error generating HTML: %v\n", err)
			return
		}
		doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(bytes)))
		if err != nil {
			fmt.Printf("Error generating HTML: %v\n", err)
			return
		}

		doc.Find("head").AppendHtml("<script type=\"text/javascript\">\nvar continentCode=\"EU\";\nvar doComplianceCheck=true;\n</script>\n<script src=\"/privacyservice.js\"></script>\n<script src=\"/path/to/some.js\"></script>")

		// 打印修改后的 HTML
		modifiedHtml, err := doc.Html()
		if err != nil {
			fmt.Printf("Error generating HTML: %v\n", err)
			return
		}

		w.Header().Reset(resp.Header)
		w.Header().Del("Content-Type")

		w.WriteHeader(resp.StatusCode)
		fmt.Fprint(w, modifiedHtml)

如果它是一个HTML页面,你可以将其作为HTML读取并作为HTML插入,这是我的看法…

package main

import (
	"bytes"
	"fmt"
)

var hdrbuf bytes.Buffer
var pagebuf bytes.Buffer

func main() {
	//get snippet
	snippet := `&lt;![CDATA[\n&lt;script type=\"text/javascript\"&gt;\nvar continentCode=\"EU\";\nvar doComplianceCheck=true;\n&lt;/script&gt;\n&lt;script src=\"/another.js\"&gt;&lt;/script&gt;\n&lt;script src=\"path/to/some.js\"&gt;&lt;/script&gt;]]&gt;`
	pageHTML := `&lt;head&gt;&lt;!-- SNIPPET_HERE --&gt;&lt;/head&gt;`

	// replace the INJECT_HERE "placeholder" with the snippet
	placeholder := []byte(`&lt;!-- SNIPPET_HERE --&gt;`)
	combined_page := bytes.ReplaceAll([]byte(pageHTML), placeholder, []byte(snippet))

	fmt.Println(string(combined_page))
	// Expected output: &lt;body&gt;&lt;div&gt;injected header&gt;&lt;/div&gt;&lt;/body&gt;
}

Go Playground

Go Playground - The Go Programming Language

或者,你可以根据需要使用 <iframe><embed> 进行测试。

在Go中向HTML文档的head标签插入多个元素,可以使用golang.org/x/net/html库。以下是一个完整的示例:

package main

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

func insertIntoHead(doc *html.Node, content string) error {
    // 查找head标签
    var head *html.Node
    var findHead func(*html.Node)
    findHead = func(n *html.Node) {
        if n.Type == html.ElementNode && n.Data == "head" {
            head = n
            return
        }
        for c := n.FirstChild; c != nil; c = c.NextSibling {
            findHead(c)
        }
    }
    findHead(doc)
    
    if head == nil {
        return fmt.Errorf("head tag not found")
    }
    
    // 解析要插入的内容
    frag, err := html.ParseFragment(strings.NewReader(content), head)
    if err != nil {
        return err
    }
    
    // 将解析后的节点插入到head末尾
    for _, node := range frag {
        head.AppendChild(node)
    }
    
    return nil
}

func main() {
    // 示例HTML文档
    htmlStr := `<!DOCTYPE html>
<html>
<head>
    <title>Test Page</title>
</head>
<body>
    <h1>Hello World</h1>
</body>
</html>`
    
    // 要插入的内容
    content := `<![CDATA[
<script type="text/javascript">
var continentCode="EU";
var doComplianceCheck=true;
</script>
<script src="/another.js"></script>
<script src="path/to/some.js"></script>]]>`
    
    // 解析HTML
    doc, err := html.Parse(strings.NewReader(htmlStr))
    if err != nil {
        panic(err)
    }
    
    // 插入内容到head
    err = insertIntoHead(doc, content)
    if err != nil {
        panic(err)
    }
    
    // 输出修改后的HTML
    var buf bytes.Buffer
    html.Render(&buf, doc)
    fmt.Println(buf.String())
}

对于CDATA部分,需要特殊处理。以下是处理CDATA的版本:

func insertCDATAScripts(doc *html.Node) error {
    var head *html.Node
    var findHead func(*html.Node)
    findHead = func(n *html.Node) {
        if n.Type == html.ElementNode && n.Data == "head" {
            head = n
            return
        }
        for c := n.FirstChild; c != nil; c = c.NextSibling {
            findHead(c)
        }
    }
    findHead(doc)
    
    if head == nil {
        return fmt.Errorf("head tag not found")
    }
    
    // 创建第一个script标签
    script1 := &html.Node{
        Type: html.ElementNode,
        Data: "script",
        Attr: []html.Attribute{{Key: "type", Val: "text/javascript"}},
    }
    script1.AppendChild(&html.Node{
        Type: html.TextNode,
        Data: "\nvar continentCode=\"EU\";\nvar doComplianceCheck=true;\n",
    })
    
    // 创建第二个script标签
    script2 := &html.Node{
        Type: html.ElementNode,
        Data: "script",
        Attr: []html.Attribute{{Key: "src", Val: "/another.js"}},
    }
    
    // 创建第三个script标签
    script3 := &html.Node{
        Type: html.ElementNode,
        Data: "script",
        Attr: []html.Attribute{{Key: "src", Val: "path/to/some.js"}},
    }
    
    // 插入到head中
    head.AppendChild(script1)
    head.AppendChild(script2)
    head.AppendChild(script3)
    
    return nil
}

// 使用示例
func main() {
    htmlStr := `<!DOCTYPE html>
<html>
<head>
    <title>Test Page</title>
</head>
<body>
    <h1>Hello World</h1>
</body>
</html>`
    
    doc, err := html.Parse(strings.NewReader(htmlStr))
    if err != nil {
        panic(err)
    }
    
    err = insertCDATAScripts(doc)
    if err != nil {
        panic(err)
    }
    
    var buf bytes.Buffer
    html.Render(&buf, doc)
    fmt.Println(buf.String())
}

输出结果将包含插入到head标签中的三个script标签。第一个包含内联JavaScript代码,后两个引用外部JS文件。

回到顶部