|
| 1 | +# Proposal: Raw XML Token |
| 2 | + |
| 3 | +Author(s): Sam Whited <sam@samwhited.com> |
| 4 | + |
| 5 | +Last updated: 2018-09-01 |
| 6 | + |
| 7 | +Discussion at https://golang.org/issue/26756 |
| 8 | + |
| 9 | +CL at https://golang.org/cl/127435 |
| 10 | + |
| 11 | + |
| 12 | +## Abstract |
| 13 | + |
| 14 | +This proposal defines a mechanism by which users can emulate the `,innerxml` |
| 15 | +struct tag using XML tokens. |
| 16 | + |
| 17 | + |
| 18 | +## Background |
| 19 | + |
| 20 | +When using the `"*Encoder".EncodeToken` API to write tokens to an XML stream, |
| 21 | +it is currently not possible to fully emulate the behavior of `Marshal`. |
| 22 | +Specifically, there is no functionality that lets users output XML equivalent to |
| 23 | +the `,innerxml` struct tag which inserts raw, unescaped, XML into the output. |
| 24 | +For example, consider the following: |
| 25 | + |
| 26 | + e := xml.NewEncoder(os.Stdout) |
| 27 | + e.Encode(struct { |
| 28 | + XMLName xml.Name `xml:"raw"` |
| 29 | + Inner string `xml:",innerxml"` |
| 30 | + }{ |
| 31 | + Inner: `<test:test xmlns:test="urn:example:golang"/>`, |
| 32 | + }) |
| 33 | + // Output: <raw><test:test xmlns:test="urn:example:golang"/></raw> |
| 34 | + |
| 35 | +This cannot be done with the token based output because all token types are |
| 36 | +currently escaped. |
| 37 | +For example, attempting to output the raw XML as character data results in the |
| 38 | +following: |
| 39 | + |
| 40 | + e.EncodeToken(xml.CharData(rawOut)) |
| 41 | + e.Flush() |
| 42 | + // <test:test xmlns:test="urn:example:golang"> |
| 43 | + |
| 44 | + |
| 45 | +## Proposal |
| 46 | + |
| 47 | +The proposed API introduces an XML pseudo-token: `RawXML`. |
| 48 | + |
| 49 | +```go |
| 50 | +// RawXML represents some data that should be passed through without escaping. |
| 51 | +// Like a struct field with the ",innerxml" tag, RawXML is written to the |
| 52 | +// stream verbatim and is not subject to the usual escaping rules. |
| 53 | +type RawXML []byte |
| 54 | + |
| 55 | +// Copy creates a new copy of RawXML. |
| 56 | +func (r RawXML) Copy() RawXML { … } |
| 57 | +``` |
| 58 | + |
| 59 | + |
| 60 | +## Rationale |
| 61 | + |
| 62 | +When attempting to match the output of legacy XML encoders which may produce |
| 63 | +broken escaping, or match the output of XML encoders that support features that |
| 64 | +are not currently supported by the [`encoding/xml`] package such as namespace |
| 65 | +prefixes it is often desirable to use `,rawxml`. |
| 66 | +However, if the user is primarily using the token stream API, it may not be |
| 67 | +desirable to switch between encoding tokens and encoding native structures which |
| 68 | +is cumbersome and forces a call to `Flush`. |
| 69 | + |
| 70 | +Being able to generate the same output from both the SAX-like and DOM-like APIs |
| 71 | +would also allow future proposals the option of fully unifying the two APIs by |
| 72 | +creating an encoder equivalent to the `NewTokenDecoder` function. |
| 73 | + |
| 74 | + |
| 75 | +## Compatibility |
| 76 | + |
| 77 | +This proposal introduces one new exported type that would be covered by the |
| 78 | +compatibility promise. |
| 79 | + |
| 80 | + |
| 81 | +## Implementation |
| 82 | + |
| 83 | +Implementation of this proposal is trivial, comprising some 5 lines of code |
| 84 | +(excluding tests and comments). |
| 85 | +[CL 127435] has been created to demonstrate the concept. |
| 86 | + |
| 87 | + |
| 88 | +## Open issues |
| 89 | + |
| 90 | +None. |
| 91 | + |
| 92 | + |
| 93 | +[`encoding/xml`]: https://golang.org/pkg/encoding/xml/ |
| 94 | +[CL 127435]: https://golang.org/cl/127435 |
0 commit comments