I have the following struct:
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"`
}
And I use the encoding/xml to encode this and then display it on web page.
The ProductName field needs to be enclosed with <![CDATA[]]. But if I write it as <![CDATA[ + p.ProductName + ]]>, the < and > will be translated to < and >.
How can I create the CDATA at minimal cost?
CDATA sections can appear inside element content and allow < and & character literals to appear. A CDATA section begins with the character sequence <! [CDATA[ and ends with the character sequence ]]>. Between the two character sequences, an XML processor ignores all markup characters such as <, >, and &.
In current Java DOM implementation you can access CDATA simply as text data using e. getTextContent() . See example without type check, cast, e. getData() .
A CDATA section is used to mark a section of an XML document, so that the XML parser interprets it only as character data, and not as markup. It comes handy when one XML data need to be embedded within another XML document.
No, The markup denoting a CDATA Section is not permitted as the value of an attribute.
@spirit-zhang: since Go 1.6, you can now use ,cdata tags:
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))
}
Outputs:
<root>
  <summary><![CDATA[<a href="http://example.org">My Example Website</a>]]></summary>
</root>
Playground: https://play.golang.org/p/xRn6fe0ilj
The rules are basically: 1) it has to be ,cdata, you can't specify the node name and 2) use the xml.Name to name the node as you want.
This is how most of the custom stuff for Go 1.6+ and XML works these days (embedded structs with xml.Name).
EDIT: Added xml:"summary" to the RootElement struct, so you can you can also Unmarshal the xml back to the struct in reverse (required to be set in both places).
I'm not sure which version of go the innerxml tag became available in, but it allows you to include data which won't be escaped:
Code:
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¶m2=bar")
    s.Escaped = "http://www.example.com/?param1=foo¶m2=bar"
    data, _ := xml.MarshalIndent(s, "", "\t")
    os.Stdout.Write(data)
}
Output:
<SomeXML>
    <Unescaped><![CDATA[http://www.example.com/?param1=foo¶m2=bar]]></Unescaped>
    <Escaped>http://www.example.com/?param1=foo&param2=bar</Escaped>
</SomeXML>
                        CDATA with ",cdata" notation. It is handy to create struct with "Cdata" and use along with your xml object
package main
import (
    "encoding/xml"
    "fmt"
)
type Person struct {
    Name    string `xml:"Name"`
    Age     int    `xml:"AGE"`
    Address Cdata  `xml:"ADDRESS"`
}
type Cdata struct {
    Value string `xml:",cdata"`
}
func main() {
    var address Cdata
    address.Value = "John's House, <House #>: 10,Universe  PIN: 00000 😜 "
    var person Person
    person.Name = "John"
    person.Age = 12
    person.Address = address
    xml, err := xml.MarshalIndent(person, "", "  ")
    if err != nil {
        fmt.Println("oopsie:", err.Error())
        return
    }
    fmt.Println(string(xml))
}
Output:
<Person>
  <Name>John</Name>
  <AGE>12</AGE>
  <ADDRESS><![CDATA[John's House, <House #>: 10,Universe  PIN: 00000 😜 ]]></ADDRESS>
</Person>
Playground: https://play.golang.org/p/sux2_JB-hkt
As @Tomalak mentioned, outputting CDATA is not supported.
You can probably write ![CDATA[ as xml tag and later on replace the closing tag from the resulting xml. Will this work for you? Its probably not the one with minimal costs, but easiest. You can of course replace the MarshalIndent call with just the Marshal call in the example below. 
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))
}
                        Expanding on the answer by @BeMasher, you can use the xml.Marshaller interface to do the work for you.
package main
import (
    "encoding/xml"
    "os"
)
type SomeXML struct {
    Unescaped CharData
    Escaped   string
}
type CharData string
func (n CharData) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    return e.EncodeElement(struct{
        S string `xml:",innerxml"`
    }{
        S: "<![CDATA[" + string(n) + "]]>",
    }, start)
}
func main() {
    var s SomeXML
    s.Unescaped = "http://www.example.com/?param1=foo¶m2=bar"
    s.Escaped = "http://www.example.com/?param1=foo¶m2=bar"
    data, _ := xml.MarshalIndent(s, "", "\t")
    os.Stdout.Write(data)
}
Output:
<SomeXML>
    <Unescaped><![CDATA[http://www.example.com/?param1=foo¶m2=bar]]></Unescaped>
    <Escaped>http://www.example.com/?param1=foo&param2=bar</Escaped>
</SomeXML>
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With