2017-01-31 2 views
0

WeChat Nachrichtenantwort erfordert ein solches Format, CDATA soll die Sonderzeichen auflösen.Wie mache ich das benutzerdefinierte CDATA-Format (String) im Golang?

<xml> 
<ToUserName><![CDATA[toUser]]></ToUserName> 
<FromUserName><![CDATA[fromUser]]></FromUserName> 
<CreateTime>12345678</CreateTime> 
<MsgType><![CDATA[text]]></MsgType> 
<Content><![CDATA[hello world]]></Content> 
</xml> 

Wenn golang mit der Spezifikation zu erreichen, fand ich, dass die xml.Marshal() kann xml:",cdata" mit dem Struktur-Tag verwendet werden. Definieren Sie eine Struktur zu behandeln, scheint die Codes wie:

package main 

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

type TextMsg struct { 
    XMLName  xml.Name `xml:"xml"` 
    ToUserName CDATA 
    FromUserName CDATA 
    CreateTime int64 
    MsgType  CDATA 
    Content  CDATA 
} 

type CDATA struct { 
    Text string `xml:",cdata"` 
} 

func main() { 
    msg := TextMsg{ 
     ToUserName: CDATA{"userId"}, 
     FromUserName: CDATA{"appId"}, 
     CreateTime: time.Now().Unix(), 
     MsgType:  CDATA{"text"}, 
     Content:  CDATA{"some message like <hello>"}} 

    b, _ := xml.MarshalIndent(msg, "", " ") 
    fmt.Println(string(b)) 
} 

Ausgabeergebnisse:

<xml> 
    <ToUserName><![CDATA[userId]]></ToUserName> 
    <FromUserName><![CDATA[appId]]></FromUserName> 
    <CreateTime>1485837083</CreateTime> 
    <MsgType><![CDATA[text]]></MsgType> 
    <Content><![CDATA[some message like <hello>]]></Content> 
</xml> 

Aber ich denke, es ist nicht perfekt, da variable Zuordnung nicht so bequem wie das ist normaler String-Typ, also ändere ich den CDATA in einen String-Typ und versuche MarshalXML() zu erreichen:

package main 

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

type TextMsg struct { 
    XMLName  xml.Name `xml:"xml"` 
    ToUserName CDATA 
    FromUserName CDATA 
    CreateTime int64 
    MsgType  CDATA 
    Content  CDATA 
} 

type CDATA string 

func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { 
    e.EncodeElement("<![CDATA["+string(c)+"]]>", start) 
    return nil 
} 

func main() { 
    msg := TextMsg{ 
     ToUserName: "userId", 
     FromUserName: "appId", 
     CreateTime: time.Now().Unix(), 
     MsgType:  "text", 
     Content:  "some message like <hello>"} 

    b, _ := xml.MarshalIndent(msg, "", " ") 
    fmt.Println(string(b)) 
} 

Aber die Ausgangsergebnisse erfüllen nicht die Erwartungen „<“ oder „>“ ist entkommen:

<xml> 
    <ToUserName>&lt;![CDATA[userId]]&gt;</ToUserName> 
    <FromUserName>&lt;![CDATA[appId]]&gt;</FromUserName> 
    <CreateTime>1485837470</CreateTime> 
    <MsgType>&lt;![CDATA[text]]&gt;</MsgType> 
    <Content>&lt;![CDATA[some message like &lt;hello&gt;]]&gt;</Content> 
</xml> 

Haben Sie gute Vorschläge für mich, danke.

Antwort

0

Sie können eine weitere Struktur CDATA2 mit dem Tag xml:",cdata" erstellen und an EncodeElement() übergeben.

EncodeElement() würde korrekt codieren CDATA2{"foo<>"} zu <![CDATA[foo<>]]>.

type CDATA2 struct { 
    Text string `xml:",cdata"` 
} 

func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { 
    e.EncodeElement(CDATA2{string(c)}, start) 
    return nil 
} 

Überprüfen Sie es in: Go Playground

bearbeiten: Sie anonyme Struktur verwenden können, wenn Sie wollen nicht definieren genannten Art

func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { 
    e.EncodeElement(struct { 
     string `xml:",cdata"` 
    }{string(c)}, start) 
    return nil 
} 

Überprüfen Sie es in: Go Playground

+0

Vielen Dank! Es ist wirklich eine gute Idee. Ich änderte den Code, so dass die zusätzliche Struktur nicht exportiert werden würde: 'func (c CDATA) Mar shalXML (e * xml.Encoder starten xml.StartElement) Fehler { \t return e.EncodeElement (struct { \t \t string "xml: \", CDATA \ "" \t} {string (c)}, Start) } ' – woylyn

+0

@woylyn Gern geschehen. Da scheint dein Code viel schlauer zu sein. Ich würde die Antwort bearbeiten. – ymonad

Verwandte Themen