问题 如何用go创建xml的CDATA节点?
我有以下结构:
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"`
}
我用的是 encoding/xml
对此进行编码然后在网页上显示。
该 ProductName
字段需要附上 <![CDATA[]]
。但如果我把它写成 <![CDATA[ + p.ProductName + ]]>
, <
和 >
将被翻译成 <
和 >
。
我怎样才能创建 CDATA
以最低的成本?
7986
2018-01-07 07:24
起源
答案:
正如@Tomalak所说,不支持输出CDATA。
你可以写 ![CDATA[
作为xml标记,稍后将从生成的xml中替换结束标记。这对你有用吗?它可能不是成本最低的,但最简单的。你当然可以在下面的例子中用Marshal调用替换MarshalIndent调用。
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))
}
2
2018-01-07 15:28
我不确定哪个版本的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¶m2=bar")
s.Escaped = "http://www.example.com/?param1=foo¶m2=bar"
data, _ := xml.MarshalIndent(s, "", "\t")
os.Stdout.Write(data)
}
输出:
<SomeXML>
<Unescaped><![CDATA[http://www.example.com/?param1=foo¶m2=bar]]></Unescaped>
<Escaped>http://www.example.com/?param1=foo&param2=bar</Escaped>
</SomeXML>
6
2017-10-27 18:22
@ 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))
}
输出:
<root>
<summary><![CDATA[<a href="http://example.org">My Example Website</a>]]></summary>
</root>
操场: https://play.golang.org/p/xRn6fe0ilj
规则基本上是:1)必须如此 ,cdata
,你不能指定节点名称和2)使用 xml.Name
根据需要命名节点。
这就是Go 1.6+和XML的大多数自定义内容最近的工作方式(嵌入式结构) xml.Name
)。
编辑:添加 xml:"summary"
到了 RootElement
结构,所以你也可以 Unmarshal
xml反向返回结构(需要在两个地方设置)。
5
2018-02-05 20:24
通过@BeMasher扩展答案,您可以使用 xml.Marshaller
界面为你做的工作。
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)
}
输出:
<SomeXML>
<Unescaped><![CDATA[http://www.example.com/?param1=foo¶m2=bar]]></Unescaped>
<Escaped>http://www.example.com/?param1=foo&param2=bar</Escaped>
</SomeXML>
2
2018-02-02 22:20
如果您使用Go版本1.6或更高版本,只需添加'cdata'标记就可以了。
type XMLProduct struct {
XMLName xml.Name `xml:"row"`
ProductId string `xml:"product_id"`
ProductName string `xml:"product_name,cdata"`
OriginalPrice string `xml:"original_price"`
BargainPrice string `xml:"bargain_price"`
TotalReviewCount int `xml:"total_review_count"`
AverageScore float64 `xml:"average_score"`
}
1
2018-06-29 05:35