github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/encoding/xml/marshal.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package xml 6 7 import ( 8 "github.com/shogo82148/std/io" 9 "github.com/shogo82148/std/reflect" 10 ) 11 12 const ( 13 // Headerは、[Marshal] の出力と一緒に使用するのに適した一般的なXMLヘッダーです。 14 // これはこのパッケージの出力に自動的に追加されるものではなく、便宜上提供されています。 15 Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n" 16 ) 17 18 // Marshalは、vのXMLエンコーディングを返します。 19 // 20 // Marshalは、配列またはスライスを処理するために、各要素をマーシャリングします。 21 // Marshalは、ポインタが指す値をマーシャリングするか、ポインタがnilの場合は何も書き込まないことで、ポインタを処理します。 22 // Marshalは、インターフェース値が含む値をマーシャリングするか、インターフェース値がnilの場合は何も書き込まないことで、インターフェース値を処理します。 23 // Marshalは、その他のすべてのデータを処理するために、データを含む1つ以上のXML要素を書き込みます。 24 // 25 // XML要素の名前は、以下の優先順位で取得されます: 26 // - データが構造体の場合、XMLNameフィールドのタグ 27 // - [Name] 型のXMLNameフィールドの値 28 // - データを取得するために使用された構造体フィールドのタグ 29 // - データを取得するために使用された構造体フィールドの名前 30 // - マーシャルされた型の名前 31 // 32 // 構造体のXML要素には、構造体のエクスポートされた各フィールドのマーシャルされた要素が含まれますが、以下の例外があります: 33 // - 上記で説明したXMLNameフィールドは省略されます。 34 // - タグ "-" のフィールドは省略されます。 35 // - タグ "name,attr" のフィールドは、XML要素内で指定された名前の属性になります。 36 // - タグ ",attr" のフィールドは、XML要素内でフィールド名の属性になります。 37 // - タグ ",chardata" のフィールドは、文字データとして書き込まれ、XML要素としては書き込まれません。 38 // - タグ ",cdata" のフィールドは、<![CDATA[ ... ]]>タグで囲まれた文字データとして書き込まれ、XML要素としては書き込まれません。 39 // - タグ ",innerxml" のフィールドは、通常のマーシャリング手順に従わず、そのまま書き込まれます。 40 // - タグ ",comment" のフィールドは、通常のマーシャリング手順に従わず、XMLコメントとして書き込まれます。これには "--" 文字列を含めることはできません。 41 // - "omitempty" オプションを含むタグのフィールドは、フィールド値が空の場合に省略されます。空の値は false、0、nil ポインタまたはインターフェース値、長さゼロの配列、スライス、マップ、文字列です。 42 // - 匿名の構造体フィールドは、その値のフィールドが外部の構造体の一部であるかのように処理されます。 43 // - [Marshaler] を実装するフィールドは、そのMarshalXMLメソッドを呼び出して書き込まれます。 44 // - [encoding.TextMarshaler] を実装するフィールドは、そのMarshalTextメソッドの結果をテキストとしてエンコードして書き込まれます。 45 // 46 // フィールドがタグ "a>b>c" を使用する場合、要素cは親要素aとbの内部にネストされます。 47 // 同じ親を名指す隣接するフィールドは、1つのXML要素内に囲まれます。 48 // 49 // 構造体フィールドのXML名がフィールドタグと構造体のXMLNameフィールドの両方によって定義されている場合、 50 // 名前は一致しなければなりません。 51 // 52 // 例については、[MarshalIndent] を参照してください。 53 // 54 // Marshalは、チャネル、関数、またはマップをマーシャルするように求められた場合、エラーを返します。 55 func Marshal(v any) ([]byte, error) 56 57 // Marshalerは、自身を有効なXML要素にマーシャルできるオブジェクトが実装するインターフェースです。 58 // 59 // MarshalXMLは、レシーバをゼロ個以上のXML要素としてエンコードします。 60 // 通常、配列やスライスは、エントリごとに一つの要素としてエンコードされます。 61 // startを要素タグとして使用することは必須ではありませんが、そうすることで 62 // [Unmarshal] がXML要素を正しい構造体フィールドにマッチさせることができます。 63 // 一般的な実装戦略の一つは、所望のXMLに対応するレイアウトを持つ別の 64 // 値を構築し、それをe.EncodeElementを使用してエンコードすることです。 65 // もう一つの一般的な戦略は、e.EncodeTokenを繰り返し呼び出して、 66 // XML出力を一つずつトークンとして生成することです。 67 // エンコードされたトークンのシーケンスは、ゼロ個以上の有効な 68 // XML要素を構成しなければなりません。 69 type Marshaler interface { 70 MarshalXML(e *Encoder, start StartElement) error 71 } 72 73 // MarshalerAttrは、自身を有効なXML属性にマーシャルできるオブジェクトが実装するインターフェースです。 74 // 75 // MarshalXMLAttrは、レシーバのエンコードされた値を持つXML属性を返します。 76 // 属性名としてnameを使用することは必須ではありませんが、そうすることで 77 // [Unmarshal] が属性を正しい構造体フィールドにマッチさせることができます。 78 // MarshalXMLAttrがゼロ属性 [Attr]{}を返す場合、出力には属性が生成されません。 79 // MarshalXMLAttrは、フィールドタグに"attr"オプションを持つ構造体フィールドのみで使用されます。 80 type MarshalerAttr interface { 81 MarshalXMLAttr(name Name) (Attr, error) 82 } 83 84 // MarshalIndentは [Marshal] と同様に動作しますが、各XML要素は新しい 85 // インデントされた行から始まり、その行はprefixで始まり、ネストの深さに応じて 86 // indentの一つ以上のコピーに続きます。 87 func MarshalIndent(v any, prefix, indent string) ([]byte, error) 88 89 // Encoderは、XMLデータを出力ストリームに書き込みます。 90 type Encoder struct { 91 p printer 92 } 93 94 // NewEncoderは、wに書き込む新しいエンコーダを返します。 95 func NewEncoder(w io.Writer) *Encoder 96 97 // Indentは、エンコーダを設定して、各要素が新しいインデントされた行から始まるXMLを生成します。 98 // その行はprefixで始まり、ネストの深さに応じてindentの一つ以上のコピーに続きます。 99 func (enc *Encoder) Indent(prefix, indent string) 100 101 // Encodeは、vのXMLエンコーディングをストリームに書き込みます。 102 // 103 // Goの値をXMLに変換する詳細については、[Marshal] のドキュメンテーションを参照してください。 104 // 105 // Encodeは、戻る前に [Encoder.Flush] を呼び出します。 106 func (enc *Encoder) Encode(v any) error 107 108 // EncodeElementは、vのXMLエンコーディングをストリームに書き込みます。 109 // この際、エンコーディングの最も外側のタグとしてstartを使用します。 110 // 111 // Goの値をXMLに変換する詳細については、[Marshal] のドキュメンテーションを参照してください。 112 // 113 // EncodeElementは、戻る前に [Encoder.Flush] を呼び出します。 114 func (enc *Encoder) EncodeElement(v any, start StartElement) error 115 116 // EncodeTokenは、与えられたXMLトークンをストリームに書き込みます。 117 // [StartElement] と [EndElement] トークンが適切にマッチしていない場合、エラーを返します。 118 // 119 // EncodeTokenは [Encoder.Flush] を呼び出しません。なぜなら、通常これは [Encoder.Encode] や [Encoder.EncodeElement] 120 // (またはそれらの間に呼び出されるカスタム [Marshaler] のMarshalXML)のような大きな操作の一部であり、 121 // それらは終了時にFlushを呼び出します。 122 // Encoderを作成し、EncodeやEncodeElementを使用せずに直接EncodeTokenを呼び出す呼び出し元は、 123 // XMLが基礎となるライターに書き込まれることを確認するために、終了時にFlushを呼び出す必要があります。 124 // 125 // EncodeTokenは、"xml"をTargetに設定した [ProcInst] を、ストリームの最初のトークンとしてのみ書き込むことを許可します。 126 func (enc *Encoder) EncodeToken(t Token) error 127 128 // Flushは、バッファリングされたXMLを基礎となるライターにフラッシュします。 129 // いつ必要かについての詳細は、EncodeTokenのドキュメンテーションを参照してください。 130 func (enc *Encoder) Flush() error 131 132 // エンコーダを閉じます。これは、これ以上データが書き込まれないことを示します。 133 // バッファリングされたXMLを基礎となるライターにフラッシュし、 134 // 書き込まれたXMLが無効である場合(例えば、閉じられていない要素を含む場合)にエラーを返します。 135 func (enc *Encoder) Close() error 136 137 // UnsupportedTypeErrorは、[Marshal] がXMLに変換できないタイプに遭遇したときに返されます。 138 type UnsupportedTypeError struct { 139 Type reflect.Type 140 } 141 142 func (e *UnsupportedTypeError) Error() string