解组 HTML 嵌套在 XML 中

Unmarshal HTML nested in XML

我从第三方收到一个 xml 文件,其中一个 XML 标签中有一个 HTML 元素。我不知道如何解组它以获得 href URL.

XML 示例:

<SOME_HTML>
  <a href="http://www.google.com" target="_blank">
  google</a>
</SOME_HTML>

这是我到目前为止所了解的,但没有向结构中添加任何内容:

type Href struct {
    Link string `xml:"href"`
}
type Link struct {
    URL []Href `xml:"a"`
}
type XmlFile struct {
    HTMLTag []Link `xml:"SOME_HTML"`
}

myFile := []byte(`<?xml version="1.0" encoding="utf-8"?>
<SOME_HTML>
    <a href="http://www.google.com" target="_blank">
    google</a>
</SOME_HTML>`)

var output XmlFile
err := xml.Unmarshal(myFile, &output)
fmt.Println(output) // {[]}

你可以这样做 (https://play.golang.org/p/MJzAVLBFfms):

type aElement struct {
    Href string `xml:"href,attr"`
}

type content struct {
    A aElement `xml:"a"`
}

func main() {
    test := `<SOME_HTML><a href="http://www.google.com" target="_blank">google</a></SOME_HTML>`

    var result content
    if err := xml.Unmarshal([]byte(test), &result); err != nil {
        log.Fatal(err)
    }
    fmt.Println(result)
}

解析 xml 中的所有内容,假设在 html 或其他标签(如 div)中也可能有多个 a 标签。

如果不需要,只需将 XmlFile.Links 替换为 Link 类型的 XmlFile.Link(不是 []Link

func main() {
    type Link struct {
        XMLName xml.Name `xml:"a"`
        URL     string   `xml:"href,attr"`
        Target  string   `xml:"target,attr"`
        Content string   `xml:",chardata"`
    }
    type Div struct {
        XMLName xml.Name `xml:"div"`
        Classes string   `xml:"class,attr"`
        Content string   `xml:",chardata"`
    }
    type XmlFile struct {
        XMLName xml.Name `xml:"SOME_HTML"`
        Links   []Link   `xml:"a"`
        Divs    []Div    `xml:"div"`
    }

    myFile := []byte(`<?xml version="1.0" encoding="utf-8"?>
<SOME_HTML>
    <a href="http://www.google.com" target="_blank">google</a>
    <a href="http://www.facebook.com" target="_blank">facebook</a>
    <div class="someclass">text</div>
</SOME_HTML>`)

    var output XmlFile
    err := xml.Unmarshal(myFile, &output)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(output)
}

Playground

编辑:在 xml 中添加了更多标签以展示如何解析不同的标签类型。

您可以使用常规 XML 解析器解析您发布的示例,但是 XML 语法有很多例外情况,通常被认为是有效的 HTML。

我能想到的最简单的例子是:我所知道的所有 html 解释器都理解 <br>(未闭合的 <br> 标签)与自闭合的相同 <br /> 标签。

如果您不知道服务另一端的 HTML 是如何生成的,您最好使用 HTML 解析器。

例如,有一个 golang.go/x/net/html 包,它提供了几个函数来解析 HTML :

https://play.golang.org/p/3hUogiwdRPO

func findFirstHref(n *html.Node, indent string) string {
    if n.Type == html.ElementNode {
        fmt.Println("  * scanning:" + indent + n.Data)
    }

    if n.Type == html.ElementNode && n.Data == "a" {
        for _, a := range n.Attr {
            if a.Key == "href" {
                return a.Val
            }
        }
    }
    for c := n.FirstChild; c != nil; c = c.NextSibling {
        href := findFirstHref(c, indent+"  ")
        if href != "" {
            return href
        }
    }
    return ""
}

func main() {
    doc1, err := html.Parse(strings.NewReader(sample1))
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("href in sample1:", findFirstHref(doc1, ""))
    }
    
    doc2, err := html.Parse(strings.NewReader(sample2))
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("href in sample2:", findFirstHref(doc2, ""))
    }
}

const (
    sample1 = `<?xml version="1.0" encoding="utf-8"?>
<SOME_HTML>
    <a href="http://www.google.com" target="_blank">
    google</a>
</SOME_HTML>`

    // sample2 is an invalid XML document (it has unclosed "<br>" tags):
    sample2 = `
    <p> line1 <br> line2
<a href="foobar" target="_blank">
  Some <br> text
</a>
</p>
`
)