2017-01-31 7 views
0

WeChat 메시지 회신에는 이러한 형식이 필요하며 CDATA는 특수 문자를 해결합니다. 사양을 달성 golang 사용시golang에서 사용자 정의 유형 (문자열) 마샬링 CDATA 형식을 만드는 방법은 무엇입니까?

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

, 난 xml.Marshal는() 구조체 태그 xml:",cdata" 함께 사용될 수 있음을 발견 하였다.

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)) 
} 

출력 결과 :

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

그러나 변수 할당이만큼 편리하지 않기 때문에 나는 그것이 완벽하지 생각 코드는 것 같아, 처리 할 수있는 구조체를 정의 일반 문자열 유형이므로 CDATA를 문자열 유형으로 변경하고 MarshalXML()을 구현하려고 시도합니다.

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)) 
} 

하지만 출력 결과가 기대에 부응하지 않는다 "<는"또는 ">" 이스케이프입니다 :

<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> 

당신을 감사합니다, 당신이 나에게 어떤 좋은 제안이 있습니까.

답변

0

태그가 xml:",cdata" 인 다른 구조 CDATA2을 생성하여 EncodeElement()에 전달할 수 있습니다.

EncodeElement()CDATA2{"foo<>"}에서 <![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 
} 

에서 확인 : Go Playground

편집 : Go Playground

+0

: 당신의 이름 유형을 정의하지 않으려면

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

가 그것을 확인 익명 구조체를 사용할 수 있습니다 정말 고마워요. 정말 좋은 생각입니다. 코드를 변경하여 여분의 구조체를 내보낼 수 없도록했습니다 :'func (c CDATA) Mar shalXML 오류 { \t 반환 e.EncodeElement (E * xml.Encoder, xml.StartElement 시작) (구조체 { \t \t 문자열 "XML : \", CDATA의 \ "" \t} {(c)는}, 시작 문자열) }' – woylyn

+0

@woylyn 안녕하세요. 코드가 훨씬 더 똑똑해 보입니다. 나는 대답을 편집 할 것이다. – ymonad