CSVからXMLへ
このコンバータはブラウザ内でCSVを行からXML要素に変換します:<records>ルート、各行に1つの<record>要素、ヘッダーごとに1つの子タグ。タグ名は有効なXMLにサニタイズされ、テキストはエスケープされます。ドット付きヘッダーはネストされた子要素になります。アップロードは一切行いません。
CSVからXMLへとは
XMLは名前についてCSVより厳格であり、その厳格さがここでの工学上の問題全体です。'unit price'のようなヘッダーはタグになれません。なぜなら、要素名にはスペースを含めることができないからです。'2fa'もタグになれません。なぜなら、名前は数字で始めることができないからです。このコンバータは標準的な解決策を適用します――無効な文字はアンダースコアに、数字で始まる名前は先頭にアンダースコアが追加されます――これにより、すべてのヘッダーが実際のXMLパーサーが受け入れるタグを生成し、列から要素へのマッピングが可視のままになります。
CSV側はRFC 4180で解析されます:引用符内の二重引用符、コンマ、改行を考慮したステートマシン、コンマ、セミコロン、タブ、パイプでの区切り文字の自動検出、そしてサイト全体で使用されているのと同じ狭い型ポリシー――値はJSON数値文法の下でのみ数値になり、02134は先頭のゼロを保持します。ドット付きヘッダーはその構造を保持します:address.cityはドットを名前に含んだフラットなタグではなく、address要素内にcityの子要素になります。
すべてがこのブラウザのタブで動作します。CSVはページ内エンジンで解析され、XMLは解析されたレコードから構築されます。ネットワークには一切触れません――DevToolsを開き、ネットワークパネルが静まっているのを見て、プライバシーの主張が自己検証されているのを確認してください。
ラウンドトリップを確認するのは1回の貼り付けで可能です。なぜなら、XMLからCSVへコンバータはこれらの同じ規約を逆方向に読み取り、要素から行を出力するからです。
出力形式の選択がまだ開いている場合、JSONとXMLの比較がマークアップがその価値を発揮する場所とオーバーヘッドになる場所を説明しています。
変換の実際の仕組み
パイプラインは、順番に解析、展開、サニタイズ、エスケープ――その順序で、各段階は前の段階の出力のみを見ます。この順序が、引用符付きセル内のコンマが要素構造を乱すことがない理由です:グリッドはXMLが存在する前に確定し、XMLライターはCSV構文について決定を下しません。
- 解析:実際の世界の許容事項を伴うRFC 4180のルール――フィールド中間の引用符は文字通りに解釈され、末尾の空行は破棄されます。
- 展開:ヘッダーはパスとしてデコードされるため、address.cityはaddress内にcityをネストし、tags[0], tags[1]は繰り返し要素になります。
- サニタイズ:すべての要素名はXML 1.0の名前ルール――文字、数字、アンダースコア、ハイフン、ドット、コロン――に対してチェックされ、失敗箇所は修復されます。
- エスケープ:テキストコンテンツはソースに&, <, >があった場所にそれぞれ&, <, >に変換され、属性値ではさらに二重引用符がエスケープされます。
タグ名ポリシー、正確には
XML 1.0では、名前は文字、アンダースコア、コロンで始まり、数字、ハイフン、ドットで続けることができます。それ以外は禁止です。サニタイザーは禁止文字セット外の文字すべてをアンダースコアに置換し、最初の存続文字が数字になる場合は先頭にアンダースコアを接頭します――これにより、unit priceはunit_priceに、2faは_2faになり、discount%という列名はdiscount_になります。有効な名前は、CamelCaseやkebab-caseを含め、そのまま通過します。なぜなら、既に有効な名前を書き換えると、その名前を待っているコンシューマーが壊れてしまうからです。
| CSVヘッダー | 出力される要素 | 理由 |
|---|---|---|
| name | <name> | すでに有効なXML名――そのまま通過 |
| unit price | <unit_price> | スペースがアンダースコアに置換 |
| 2fa | <_2fa> | 名前は数字で始めることができない |
| address.city | <address><city> | ドット付きヘッダーはフラット化せずネストする |
値はどうなるか
XMLには数値やブール型の別々の型はありません――すべての値はテキストです――そのため、セルはその正確な文字のまま渡り、精度を失ったり創発したりする型変換はありません。空のセルは空の値ではなく欠損フィールドとして扱われ、要素は省略され、消費されない自己終了タグの文字列が出力されることはありません。エスケープは出力時に適用されます:'A & B'を含むセルはドキュメント内で'A & B'になり、結果を読み取るXMLパーサーは再び元のテキストを見ます。
- 02134は02134のままです。グリッドから離れる瞬間から値がテキストになるため、先頭のゼロは決してトリムされません。
- 複数行のセルは要素内の改行を保持し、その改行はフォーマットではなくデータです。
- <record>要素はすべての行で同じです――不揃いな行でも、その行にない列は単に要素を生成しません。
境界事象と報告方法
コンバータの拒否はその契約の支え部分です。終了していない引用符付きフィールドは、その行で名前付きエラーで解析を停止します。なぜなら、フィールドがどこで終了したか推測すると、その後のすべての行を静かに変形させてしまうからです。ヘッダーとフィールド数が異なる行は変換されますが、警告が欠損フィールドが absent であり、余分なフィールドは dropped であることを述べます。重複ヘッダーは右側の値が優先され、警告がそれを述べます――スプレッドシートインポートの動作を明示化したものです。
- 終了していない引用符:解析中止、該当行報告、出力なし。
- 不揃いな行:警告で影響を受けた行名を記載して変換。
- 重複ヘッダー:警告付きで変換;最右の出現が優先。
よくある質問
CSVをXMLに変換すると、ファイルはどこかにアップロードされますか?
いいえ。CSVの解析とXMLの構築は、ページ開時に一度だけ読み込まれたコードを使い、このブラウザタブ内で実行されます。アップロード先のエンドポイントは存在せず、ページはconnect-srcが'self'であるContent-Security-Policyで提供されるため、試みられたとしてもブラウザは送信要求を拒否します。変換中にDevToolsのネットワークパネルを確認してください――それは空のままです。
なぜ出力は<records>と<record>タブで囲まれていますか?
XMLは正確に1つのルート要素を必要とし、CSVファイルにはそれに名前を付ける自然なものがないため、コンバータは固定の形状を使用します:各行に1つの<record>要素を持つ<records>ルート。ヘッダーは各レコード内の子タブになります。ラッパーは出力を断片ではなく整形式のドキュメントにし、すべての行が/records/recordのようなXPathで容易にアドレス可能になります。
無効なタグ名はどう処理されますか?
すべてのヘッダーはXML 1.0の名前ルールにサニタイズされます:文字、数字、アンダースコア、ハイフン、ドット、コロン以外の文字はアンダースコアになり、数字で始まる名前は先頭にアンダースコアが接頭されます。そのため、unit priceはunit_priceに、2faは_2faになります。すでに有効だった名前はそのまま通過します。これは、ダウンストリームシステムが正確なタグ名でマッチングする場合に重要です。
セル値内の特殊文字はどうエスケープされますか?
テキストコンテンツはXMLが要求する3文字がエスケープされます:&は&に、<は<に、>は>になります。属性値内では二重引用符も"としてエスケープされます。エスケープは出力時のみに行われるため、'A & B'を含むセルはXMLパーサーがドキュメントを読むときに元の正確な'A & B'にラウンドトリップします――2重にエスケープされることも、事前にアンエスケープされることもありません。
数値と郵便番号のフォーマットは保持されますか?
はい、値はそのままXMLテキストになるため、再フォーマットする可能性のある数値変換ステップはありません。02134は先頭のゼロを保持し、44.95は正確な小数形式を保持し、1e5のような値は展開されるのではなく、入力した文字列のままです。型情報はCSVまたはJSONの問題です。XML要素はテキストを持ち、コンバータはそれを推測しません。
CSVに不揃いな行や重複ヘッダーがある場合はどうなりますか?
両方とも変換されますが、それぞれ明示的な警告付きです。ヘッダーより短い行は欠損フィールドで補完され――空の要素は生成されず――ヘッダーより長い行は余分なフィールドが破棄され、警告で影響を受けた行数が記載されます。重複する列名は最右が優先で、スプレッドシートインポートの動作と同じです。警告には関係する名前がリストされます。