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