twpayne/go-kml

CDATA support

estronnom opened this issue · 4 comments

Hi! I was wondering is there any way to use CDATA element with your lib?
Thanks

What exactly do you want to achieve? Could you give an exact example with code and example output?

The KML structure I'm trying to get should look like this:

<ExtendedData>
    <Data name="extraImage">
        <![CDATA[files/image_1.jpg]]>
    </Data>
</ExtendedData>

So, the code example to generate it with go-kml may look like this:

kml.ExtendedData(
		kml.Data(
			"extraImage",
			kml.CharacterData("files/image_1.jpg"), //CDATA
		),
	)

Also, an xml struct to parse such structure should utilize chardata encoding/xml tag:

type DataWithCDATA struct {
    ChardataValue string   `xml:",chardata"`
}

Thanks for the follow-up.

CDATA elements are used to escape character data. The standard library's encoding/xml (on which github.com/twpayne/go-kml is based) automatically escapes character data if needed, so, as a user you never need to think about whether you have to use CDATA.

As files/image_1.jpg does not need escaping, the following two XML documents are equivalent:

<ExtendedData>
    <Data name="extraImage">
        <![CDATA[files/image_1.jpg]]>
    </Data>
</ExtendedData>
<ExtendedData>
    <Data name="extraImage">files/image_1.jpg</Data>
</ExtendedData>

However, if the KML you are generated is consumed by a broken code that expects a CDATA directive, then you can pass any Go value that implements encoding/xml.Marshaler as a KML child element, so you can force use of a CDATA directive.

For example:

package main

import (
	"encoding/xml"
	"os"

	"github.com/twpayne/go-kml/v3"
)

type CData string

func (c CData) MarshalXML(e *xml.Encoder, startElement xml.StartElement) error {
	directive := xml.Directive([]byte("[CDATA[" + string(c) + "]]"))
	return e.EncodeToken(directive)
}

func main() {
	extendedData := kml.ExtendedData(
		kml.Data(
			"extraImage",
			CData("files/image1.jpg"),
		),
	)

	e := xml.NewEncoder(os.Stdout)
	e.Indent("", "\t")
	e.Encode(extendedData)
}

which outputs:

<ExtendedData>
	<Data name="extraImage"><![CDATA[files/image1.jpg]]></Data>
</ExtendedData>

You can see this example in the Go playground.

If you can avoid using a broken XML parser then you don't need CDATA.

Thank you! That does exactly what I needed, closing this.