如何用go创建xml的CDATA节点?

Der*_*ang 12 xml cdata go

我有以下结构:

type XMLProduct struct {
    XMLName          xml.Name `xml:"row"`
    ProductId        string   `xml:"product_id"`
    ProductName      string   `xml:"product_name"`
    OriginalPrice    string   `xml:"original_price"`
    BargainPrice     string   `xml:"bargain_price"`
    TotalReviewCount int      `xml:"total_review_count"`
    AverageScore     float64  `xml:"average_score"`
}
Run Code Online (Sandbox Code Playgroud)

我用它encoding/xml来编码,然后在网页上显示它.

ProductName字段需要附上<![CDATA[]].但是如果我把它写成<![CDATA[ + p.ProductName + ]]><,并>会被翻译成&lt;&gt;.

如何CDATA以最低成本创建?

edu*_*911 10

@ spirit-zhang:从Go 1.6开始,你现在可以使用,cdata标签:

package main

import (
    "fmt"
    "encoding/xml"
)

type RootElement struct {
    XMLName xml.Name `xml:"root"`
    Summary *Summary `xml:"summary"`
}

type Summary struct {
    XMLName xml.Name `xml:"summary"`
    Text    string   `xml:",cdata"`
}

func main() {

    cdata := `<a href="http://example.org">My Example Website</a>`
    v := RootElement{
        Summary: &Summary{
            Text: cdata,
        },
    }

    b, err := xml.MarshalIndent(v, "", "  ")
    if err != nil {
        fmt.Println("oopsie:", err)
        return
    }
    fmt.Println(string(b))
}
Run Code Online (Sandbox Code Playgroud)

输出:

<root>
  <summary><![CDATA[<a href="http://example.org">My Example Website</a>]]></summary>
</root>
Run Code Online (Sandbox Code Playgroud)

游乐场:https://play.golang.org/p/xRn6fe0ilj

规则基本上是:1)它必须是,cdata,你不能指定节点名称和2)使用xml.Name命名节点你想要的.

这就是Go 1.6+和XML的大多数自定义内容最近的工作原理(嵌入式结构xml.Name).


编辑:添加xml:"summary"RootElement结构,所以你也可以Unmarshal将xml反向返回结构(需要在两个地方设置).


BeM*_*her 6

我不确定哪个版本的innerxml标签可用,但它允许您包含不会被转义的数据:

码:

package main

import (
    "encoding/xml"
    "os"
)

type SomeXML struct {
    Unescaped CharData
    Escaped   string
}

type CharData struct {
    Text []byte `xml:",innerxml"`
}

func NewCharData(s string) CharData {
    return CharData{[]byte("<![CDATA[" + s + "]]>")}
}

func main() {
    var s SomeXML
    s.Unescaped = NewCharData("http://www.example.com/?param1=foo&param2=bar")
    s.Escaped = "http://www.example.com/?param1=foo&param2=bar"
    data, _ := xml.MarshalIndent(s, "", "\t")
    os.Stdout.Write(data)
}
Run Code Online (Sandbox Code Playgroud)

输出:

<SomeXML>
    <Unescaped><![CDATA[http://www.example.com/?param1=foo&param2=bar]]></Unescaped>
    <Escaped>http://www.example.com/?param1=foo&amp;param2=bar</Escaped>
</SomeXML>
Run Code Online (Sandbox Code Playgroud)


rpu*_*kar 3

正如@Tomalak 提到的,不支持输出 CDATA。

您可以编写![CDATA[为 xml 标记,然后替换生成的 xml 中的结束标记。这对你有用吗?它可能不是成本最低的一种,但却是最简单的一种。当然,您可以将 MarshalIndent 调用替换为以下示例中的 Marshal 调用。

http://play.golang.org/p/2-u7H85-wn

package main

import (
    "encoding/xml"
    "fmt"
    "bytes"
)

type XMLProduct struct {
    XMLName          xml.Name `xml:"row"`
    ProductId        string   `xml:"product_id"`
    ProductName      string   `xml:"![CDATA["`
    OriginalPrice    string   `xml:"original_price"`
    BargainPrice     string   `xml:"bargain_price"`
    TotalReviewCount int      `xml:"total_review_count"`
    AverageScore     float64  `xml:"average_score"`
}

func main() {
    prod := XMLProduct{
        ProductId:        "ProductId",
        ProductName:      "ProductName",
        OriginalPrice:    "OriginalPrice",
        BargainPrice:     "BargainPrice",
        TotalReviewCount: 20,
        AverageScore:     2.1}

    out, err := xml.MarshalIndent(prod, " ", "  ")
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }

    out = bytes.Replace(out, []byte("<![CDATA[>"), []byte("<![CDATA["), -1)
    out = bytes.Replace(out, []byte("</![CDATA[>"), []byte("]]>"), -1)
    fmt.Println(string(out))
}
Run Code Online (Sandbox Code Playgroud)

  • 这太可怕了,也太悲伤了。有没有人提出增强请求以更有效地实现标准 API? (7认同)
  • 这并不完全正确。解析器需要找到 CDATA 的末尾,但不能解析块中的所有字符数据。例如,这意味着可以轻松地将包含 &lt; 和 &gt; 符号的 JavaScript 代码逐字放入 XHTML 中,而无需使用 &lt; 和 &gt; 符号。或&gt; 形式。 (2认同)