2013-01-07 15 views
11

मैं निम्नलिखित 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"` 
} 

और मैं encoding/xml का उपयोग इस सांकेतिक शब्दों में बदलना और फिर वेब पेज पर प्रदर्शित करने के।

ProductName फ़ील्ड को <![CDATA[]] के साथ संलग्न करने की आवश्यकता है। लेकिन अगर मैं इसे <![CDATA[ + p.ProductName + ]]> के रूप में लिखता हूं, < और > का अनुवाद &lt; और &gt; पर किया जाएगा।

मैं न्यूनतम लागत पर CDATA कैसे बना सकता हूं?

+0

यह * की आवश्यकता क्यों है * CDATA होने के लिए? एक सीडीएटीए अनुभाग एक सुविधा सुविधा है, इसे एक्सएमएल एन्कोडेड वैल्यू के साथ इंटरचेंज किया जा सकता है और दस्तावेज़ वही होगा। – Tomalak

+3

@Tomalak यह कंपनी विनिर्देश है ... –

+0

(http://golang.org/src/pkg/encoding/xml/marshal.go) है कि यह नहीं दर्शाती है [ 'एन्कोडिंग/xml/marshal.go' के स्रोत] सीडीएटीए आउटपुट का समर्थन किया जाता है। * (फिर से, CDATA तकनीकी रूप से अनावश्यक है। हो सकता है कि विनिर्देश सब के बाद संशोधित किया जा सकता है?) * – Tomalak

उत्तर

3

जैसा कि @ टोमालक ने उल्लेख किया है, सीडीएटीए आउटपुट समर्थित नहीं है।

आप शायद ![CDATA[ को XML टैग के रूप में लिख सकते हैं और बाद में परिणामी xml से समापन टैग को प्रतिस्थापित कर सकते हैं। क्या यह आपके लिए काम करेगा? शायद यह न्यूनतम लागत वाला नहीं है, लेकिन सबसे आसान है। आप निश्चित रूप से नीचे दिए गए उदाहरण में मार्शल कॉल के साथ मार्शल इंडेंट कॉल को प्रतिस्थापित कर सकते हैं।

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

यह भयानक और काफी दुखी है। क्या किसी ने मानक एपीआई में अधिक कुशल कार्यान्वयन के लिए एक वृद्धि अनुरोध दायर किया है? –

+0

@ रिक -777: यदि सुविधा के लिए वैध आवश्यकता थी, तो शायद। लेकिन जैसा कि अन्य टिप्पणियों ने कहा है, एक्सएमएल पार्सर्स को सीडीएटीए ब्लॉक और समकक्ष एन्कोडेड कैरेक्टर डेटा का इलाज करने की आवश्यकता है, इसलिए एन्कोडिंग के दौरान कौन सा संस्करण उपयोग किया जाता है, इस पर ध्यान देने का कोई कारण नहीं है। –

+2

यह पूरी तरह से सही नहीं है। पार्सर को सीडीएटीए का अंत ढूंढना आवश्यक है लेकिन अन्यथा ब्लॉक में सभी वर्ण डेटा को पार्स नहीं करना है। यह उदाहरण के लिए < या > फार्म का उपयोग करने के लिए की जरूरत के बिना एक्सएचटीएमएल में < and > प्रतीक वाले शब्दशः जावास्क्रिप्ट कोड डाल करने के लिए आसान है,, का मतलब है। –

5

मैं जो 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) 
} 

आउटपुट:

<SomeXML> 
    <Unescaped><![CDATA[http://www.example.com/?param1=foo&param2=bar]]></Unescaped> 
    <Escaped>http://www.example.com/?param1=foo&amp;param2=bar</Escaped> 
</SomeXML> 
1

@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&param2=bar" 
    s.Escaped = "http://www.example.com/?param1=foo&param2=bar" 
    data, _ := xml.MarshalIndent(s, "", "\t") 
    os.Stdout.Write(data) 
} 

आउटपुट:

<SomeXML> 
    <Unescaped><![CDATA[http://www.example.com/?param1=foo&param2=bar]]></Unescaped> 
    <Escaped>http://www.example.com/?param1=foo&amp;param2=bar</Escaped> 
</SomeXML> 
1

आपके द्वारा जाएं संस्करण 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"` 
} 
+0

'[] xml: प्रकार main.XMLProduct के क्षेत्र ProductName में अमान्य टैग: "product_name, cdata" ' – Bryce

4

@ भावना झांग:

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> 

खेल का मैदान: जाओ 1.6 के बाद से, आप अब ,cdata टैग का उपयोग कर सकते हैं https://play.golang.org/p/xRn6fe0ilj

नियम मूल रूप से कर रहे हैं : 1) यह ,cdata होना चाहिए, आप नोड नाम निर्दिष्ट नहीं कर सकते हैं और 2) जैसा कि आप चाहते हैं नोड नाम देने के लिए xml.Name का उपयोग करें।

इस प्रकार गो 1.6+ और एक्सएमएल के लिए कस्टम सामग्री का अधिकांश दिन इन दिनों काम करता है (xml.Name के साथ एम्बेडेड structs)।


संपादित करें: xml:"summary"RootElement struct के लिए जोड़ा गया है, तो आप आप भी Unmarshal एक्सएमएल वापस रिवर्स में struct करने के लिए (दोनों ही स्थानों पर स्थापित किया जाना आवश्यक है) कर सकते हैं कर सकते हैं।

+1

यह उत्तर मेरे लिए काम किया। – Melvin

+0

संपादित करें: Unmarshal xml को एक स्ट्रक्चर में वापस करने की क्षमता को जोड़ा गया था (एक 'xml' टैग गुम था) – eduncan911

संबंधित मुद्दे