Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12312] ファイルの概要

このコミットは、Go言語の標準ライブラリであるencoding/xmlパッケージ内のテストファイルmarshal_test.goにおけるXMLタグの利用方法を修正するものです。具体的には、構造体フィールドに付与するxmlタグの記述をより明示的な形式に統一し、それに伴いXMLマーシャリングの期待値(ExpectXML)を調整しています。この変更は「実際の問題ではない」とされていますが、テストの正確性を向上させ、encoding/xmlパッケージのchardata(文字データ)処理の意図を明確にするためのものです。

コミット

commit b5d4cffd152cb3194f78c17df7bcf8dcde697947
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date:   Thu Mar 1 15:20:13 2012 -0300

    encoding/xml: fix xml test tag usage

    No real problem.

    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/5717049

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/b5d4cffd152cb3194f78c17df7bcf8dcde697947

元コミット内容

encoding/xml: fix xml test tag usage

No real problem.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5717049

変更の背景

このコミットは、encoding/xmlパッケージのテストコードにおけるXMLタグの記述方法の整合性を高めることを目的としています。コミットメッセージには「No real problem.(実際の問題ではない)」とありますが、これは既存のコードが誤動作していたわけではなく、テストの意図やencoding/xmlの挙動をより正確に反映させるための改善であることを示唆しています。

Go言語のencoding/xmlパッケージは、Goの構造体とXMLドキュメント間のマーシャリング(Go構造体からXMLへの変換)およびアンマーシャリング(XMLからGo構造体への変換)を扱うためのものです。このパッケージでは、構造体のフィールドに「構造体タグ(struct tag)」を付与することで、XML要素名や属性、データ形式などを制御します。

以前のコードでは、xml:",chardata"という形式でタグが記述されていましたが、これはGoの構造体タグの一般的な慣習(key:"value")から逸脱していました。この変更は、xml:"key,option"という標準的な形式に合わせることで、コードの可読性と一貫性を向上させ、将来的な誤解を防ぐためのものです。特に、chardataオプションがXMLタグの一部であることを明示することで、その意味がより明確になります。また、chardataとして扱われるフィールドがXML出力においてどのように表現されるべきかという、encoding/xmlの正しい挙動をテストが正確に反映するように修正されています。

前提知識の解説

1. Go言語のencoding/xmlパッケージ

encoding/xmlパッケージは、Go言語でXMLデータを扱うための標準ライブラリです。主な機能は以下の通りです。

  • マーシャリング (Marshaling): Goの構造体インスタンスをXMLドキュメントに変換します。
  • アンマーシャリング (Unmarshaling): XMLドキュメントをGoの構造体インスタンスに変換します。

このパッケージは、Goの構造体フィールドに付与される「構造体タグ」を利用して、XML要素名、属性、テキストコンテンツ(chardata)などのマッピングを制御します。

2. Goの構造体タグ (Struct Tags)

Go言語の構造体フィールドには、バッククォート(`)で囲まれた文字列として「構造体タグ」を付与できます。これらのタグは、リフレクション(reflection)を通じて実行時に読み取られ、JSON、XML、データベースなど、外部データ形式とのマッピングやバリデーションルールなどを定義するために広く利用されます。

XMLマーシャリング/アンマーシャリングにおいては、xml:"name,options"という形式でタグを使用します。

  • name: XML要素名または属性名を指定します。省略された場合、フィールド名が小文字で使われます。
  • options: カンマ区切りで追加のオプションを指定します。

例:

type Person struct {
    Name string `xml:"name,attr"` // "name"属性としてマッピング
    Age  int    `xml:"age"`       // "age"要素としてマッピング
    Bio  string `xml:",chardata"` // 親要素のテキストコンテンツとしてマッピング
}

3. XMLのchardata (Character Data)

XMLにおいて、chardataは要素の開始タグと終了タグの間に含まれるテキストコンテンツを指します。これは、子要素や属性とは異なり、要素自身の値として扱われます。

Goのencoding/xmlパッケージでは、構造体フィールドにxml:",chardata"タグを付与することで、そのフィールドが親XML要素のテキストコンテンツとしてマーシャリング/アンマーシャリングされることを指定します。

例: Go構造体:

type Book struct {
    Title  string `xml:"title"`
    Author string `xml:"author"`
    Content string `xml:",chardata"` // Book要素のテキストコンテンツ
}

この構造体をマーシャリングすると、以下のようなXMLが生成される可能性があります。

<Book>
    <title>Go Programming</title>
    <author>Gopher</author>
    これは本のコンテンツです。
</Book>

ここで、"これは本のコンテンツです。" の部分がContentフィールドにマッピングされるchardataです。

4. XMLマーシャリングの挙動

encoding/xmlパッケージは、構造体のフィールドをXML要素に変換する際に、以下のルールに従います。

  • タグがない場合: フィールド名がXML要素名として使用されます(例: Valueフィールドは<Value>要素になる)。
  • xml:"name"タグがある場合: 指定されたnameがXML要素名として使用されます。
  • xml:",chardata"タグがある場合: そのフィールドは、親要素のテキストコンテンツとして扱われ、自身のXML要素は生成されません。

このコミットの変更は、特に最後のxml:",chardata"の挙動と、それがテストでどのように期待されるべきかに関連しています。

技術的詳細

このコミットの技術的な核心は、Goのencoding/xmlパッケージにおける構造体タグの解釈と、chardataオプションの正確な挙動にあります。

xml:",chardata"タグの正確な意味と影響

xml:",chardata"タグは、そのフィールドがXML要素のテキストコンテンツ(Character Data)として扱われるべきであることをencoding/xmlパッケージに指示します。このタグが付与されたフィールドは、マーシャリング時に自身のXML要素(例: <Value>...</Value>) を生成せず、親要素の直接の子テキストとして出力されます。

このコミット以前のコードでは、Value string ",chardata"という記述がありました。これは、Goの構造体タグの一般的な構文(key:"value")から見ると、keyが省略され、value",chardata"となっているように見えます。しかし、encoding/xmlパッケージの内部実装では、xml:プレフィックスがない場合でも、特定のオプション(例: chardata)が認識されることがありました。これは、Goの初期のバージョンにおけるタグパーシングの柔軟性、あるいは意図しない挙動だった可能性があります。

このコミットでは、Value string ",chardata"Value string xml:",chardata"に修正しています。この変更により、xml:プレフィックスが明示的に追加され、chardataオプションがxml`タグの一部として明確に指定されるようになりました。これは、Goの構造体タグの標準的な記述方法に準拠し、コードの意図をより明確にするためのものです。

テストケースの変更がencoding/xmlの正しい挙動を反映

この変更に伴い、marshalTests配列内の期待されるXML出力(ExpectXML)も修正されています。

変更前:

<InTag><Value>A</Value></InTag>
<InXMLName><Value>B</Value></InXMLName>
<InXMLNameTag><Value>C</Value></InXMLNameTag>

変更後:

<InTag>A</InTag>
<InXMLName>B</InXMLName>
<InXMLNameTag>C</InXMLNameTag>

この修正は、xml:",chardata"が正しく解釈された場合のXMLマーシャリングの挙動を正確に反映しています。 XMLNameWithTagおよびXMLNameWithoutTag構造体において、Valueフィールドはxml:",chardata"タグを持つように定義されています。このタグの目的は、Valueフィールドの内容が、その親要素(この場合はXMLNameWithTagXMLNameWithoutTagがマッピングされる要素)の直接のテキストコンテンツとして出力されることです。

したがって、構造体がXMLにマーシャリングされる際、Valueフィールドは自身の<Value>タグを生成するのではなく、親要素の内部に直接その値(例: "A", "B", "C")を挿入します。

例えば、XMLNameWithTag構造体が<InXMLNameTag>要素にマッピングされる場合、その内部のValueフィールドが"C"であれば、期待される出力は<InXMLNameTag>C</InXMLNameTag>となります。変更前のテストでは、誤って<InXMLNameTag><Value>C</Value></InXMLNameTag>というネストされた構造を期待していましたが、これはchardataの意図に反していました。

このコミットは、テストコードがencoding/xmlパッケージのchardata処理の正しいセマンティクスを反映するように修正することで、テストの信頼性と正確性を向上させています。

コアとなるコードの変更箇所

--- a/src/pkg/encoding/xml/marshal_test.go
+++ b/src/pkg/encoding/xml/marshal_test.go
@@ -136,12 +136,12 @@ type NamePrecedence struct {
 
 type XMLNameWithTag struct {
 	XMLName Name   `xml:"InXMLNameTag"`
-	Value   string ",chardata"
+	Value   string `xml:",chardata"`
 }
 
 type XMLNameWithoutTag struct {
 	XMLName Name
-	Value   string ",chardata"
+	Value   string `xml:",chardata"`
 }
 
 type NameInField struct {
@@ -532,9 +532,9 @@ var marshalTests = []struct {
 			InFieldName: "D",
 		},
 		ExpectXML: `<Parent>` +\
-			`<InTag><Value>A</Value></InTag>` +\
-			`<InXMLName><Value>B</Value></InXMLName>` +\
-			`<InXMLNameTag><Value>C</Value></InXMLNameTag>` +\
+			`<InTag>A</InTag>` +\
+			`<InXMLName>B</InXMLName>` +\
+			`<InXMLNameTag>C</InXMLNameTag>` +\
 			`<InFieldName>D</InFieldName>` +\
 			`</Parent>`,
 		MarshalOnly: true,
@@ -548,9 +548,9 @@ var marshalTests = []struct {
 			InFieldName: "D",
 		},
 		ExpectXML: `<Parent>` +\
-			`<InTag><Value>A</Value></InTag>` +\
-			`<FromNameVal><Value>B</Value></FromNameVal>` +\
-			`<InXMLNameTag><Value>C</Value></InXMLNameTag>` +\
+			`<InTag>A</InTag>` +\
+			`<FromNameVal>B</FromNameVal>` +\
+			`<InXMLNameTag>C</InXMLNameTag>` +\
 			`<InFieldName>D</InFieldName>` +\
 			`</Parent>`,
 		UnmarshalOnly: true,

コアとなるコードの解説

このコミットは、主にsrc/pkg/encoding/xml/marshal_test.goファイル内の2つの主要な変更を含んでいます。

1. 構造体タグの修正

 type XMLNameWithTag struct {
 	XMLName Name   `xml:"InXMLNameTag"`
-	Value   string ",chardata"
+	Value   string `xml:",chardata"`
 }
 
 type XMLNameWithoutTag struct {
 	XMLName Name
-	Value   string ",chardata"
+	Value   string `xml:",chardata"`
 }

この部分では、XMLNameWithTagXMLNameWithoutTagという2つのテスト用構造体内のValueフィールドの構造体タグが修正されています。 変更前はValue string ",chardata"と記述されていましたが、これはGoの構造体タグの標準的な形式(key:"value")から見ると、keyが省略された特殊な形式でした。 変更後はValue string xml:",chardata"となり、xml:プレフィックスが明示的に追加されています。これにより、",chardata"xmlタグのオプションとして明確に指定され、コードの意図がより明確になり、Goの構造体タグの慣習に準拠するようになりました。この修正は、encoding/xmlパッケージがこのタグを正しく解釈し、Value`フィールドの内容を親要素のテキストコンテンツとして扱うことを保証します。

2. 期待されるXML出力の修正

@@ -532,9 +532,9 @@ var marshalTests = []struct {
 			InFieldName: "D",
 		},
 		ExpectXML: `<Parent>` +\
-			`<InTag><Value>A</Value></InTag>` +\
-			`<InXMLName><Value>B</Value></InXMLName>` +\
-			`<InXMLNameTag><Value>C</Value></InXMLNameTag>` +\
+			`<InTag>A</InTag>` +\
+			`<InXMLName>B</InXMLName>` +\
+			`<InXMLNameTag>C</InXMLNameTag>` +\
 			`<InFieldName>D</InFieldName>` +\
 			`</Parent>`,
 		MarshalOnly: true,
@@ -548,9 +548,9 @@ var marshalTests = []struct {
 			InFieldName: "D",
 		},
 		ExpectXML: `<Parent>` +\
-			`<InTag><Value>A</Value></InTag>` +\
-			`<FromNameVal><Value>B</Value></FromNameVal>` +\
-			`<InXMLNameTag><Value>C</Value></InXMLNameTag>` +\
+			`<InTag>A</InTag>` +\
+			`<FromNameVal>B</FromNameVal>` +\
+			`<InXMLNameTag>C</InXMLNameTag>` +\
 			`<InFieldName>D</InFieldName>` +\
 			`</Parent>`,
 		UnmarshalOnly: true,

この部分では、marshalTestsというテストケースの配列内で定義されているExpectXML文字列が修正されています。 変更前は、Valueフィールドが<Value>...</Value>という独自のXML要素としてネストされている形式を期待していました。しかし、Valueフィールドにxml:",chardata"タグが付与されている場合、その内容は親要素の直接のテキストコンテンツとして出力されるべきです。 したがって、<InTag><Value>A</Value></InTag><InTag>A</InTag>に、<InXMLName><Value>B</Value></InXMLName><InXMLName>B</InXMLName>に、<InXMLNameTag><Value>C</Value></InXMLNameTag><InXMLNameTag>C</InXMLNameTag>に修正されています。

この修正は、encoding/xmlパッケージのchardata処理の正しい挙動をテストが正確に反映するようにするためのものです。これにより、テストがより堅牢になり、将来的なリファクタリングや変更があった場合でも、chardataのセマンティクスが正しく維持されているかを確認できるようになります。

関連リンク

参考にした情報源リンク