質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

569閲覧

オブジェクトtoXMLへ変換する関数内で、?や&を含むと処理が上手く行きません。

yuki_90453

総合スコア326

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2022/09/16 08:36

概要

payloadをxmlでPOSTする必要があるAPIがあります。
XMLは使いづらいため、オブジェクトをXMLに変換する関数を作りましたが、URLなどに?や&を含んだ場合、XMLの変換が上手くいかずAPI POST時に失敗してしまいます。

実際の関数

TypeScript

1export function OBJtoXML(obj:any) { 2 var xml = ''; 3 for (var prop in obj) { 4 xml += "<" + prop + ">"; 5 if(Array.isArray(obj[prop])) { 6 for (var array of obj[prop]) { 7 // A real botch fix here 8 xml += "</" + prop + ">"; 9 xml += "<" + prop + ">"; 10 11 xml += OBJtoXML(new Object(array)); 12 } 13 } else if (typeof obj[prop] == "object") { 14 xml += OBJtoXML(new Object(obj[prop])); 15 } else { 16 xml += obj[prop]; 17 } 18 xml += "</" + prop + ">"; 19 } 20 var xml = xml.replace(/<\/?[0-9]{1,}>/g,''); 21 return xml 22}

サンプルの引数

const param = { ShipCompanyCode: 'サンプル', ShipInvoiceNumber1: '573479387598', ShipDate: '2022/1/1', ShipUrl: `https://sample.com\?searchKind=S004\&locale=ja\&reqCodeNo1=573479387598` }

質問

おそらく原因はURLの?にあると思います。そこでエスケープを入れましたが、やはり上手く行きません。
どなたアドバイス頂けないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

To: @yuki_90453 さん

文字参照

原因は既存の回答通りエスケープされていないからで、XMLでは文字参照か数値参照でエスケープする必要があります。

アンパサンド文字(&)と左山括弧(<)は、マークアップ区切り子として使われる場合、あるいはコメント、処理命令、CDATAセクションの中に現れる場合を除き、直接現れてはならない(must not)。もしそれらの文字を他の場所で使わなければならない場合は、数値による文字参照を使うか、それぞれ文字列"&"と"<"を使うかしてエスケープしなければならない(must)。右山括弧(>)は、通常はそうする必要は無いが、文字列">"で表しても良い。但し、文字列"]]>"がCDATAセクションの終わりを意味する為に現れたのでなければ、互換性の為に、その文字列の中に現れる右山括弧を">"か文字参照を使ってエスケープしなければならない(must)。


"&" 以外に "<>" もエスケープされていない問題があります。

function OBJtoXML(obj) { var xml = ''; for (var prop in obj) { xml += "<" + prop + ">"; if (Array.isArray(obj[prop])) { for (var array of obj[prop]) { // A real botch fix here xml += "</" + prop + ">"; xml += "<" + prop + ">"; xml += OBJtoXML(new Object(array)); } } else if (typeof obj[prop] == "object") { xml += OBJtoXML(new Object(obj[prop])); } else { xml += obj[prop]; } xml += "</" + prop + ">"; } var xml = xml.replace(/<\/?[0-9]{1,}>/g, ''); return xml; } console.log(OBJtoXML({foo: '<baz>&amp;&#100;'})); // <foo><baz>&amp;&#100;</foo>

XMLSerializer.prototype.serializeToString()

一度、Document に挿入してDOM処理してから、XMLにシリアライズするのが最も確実だと思います。

javascript

1const doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null); 2const foo = doc.documentElement.appendChild(doc.createElement('foo')); 3foo.textContent = '<bar>foo&bar</bar>'; 4const str = new XMLSerializer().serializeToString(doc).replace(/^<html[^>]*>|<\/html>/g, ''); 5 6console.log(str); // <foo>&lt;bar&gt;foo&amp;bar&lt;/bar&gt;</foo>

<>& のエスケープ程度なら String#replace でも実装可能ですが、要素に扱える文字種の判定(例: "<" は要素名に指定できない)など細かな文法規則を全て自前でチェックするのは現実的ではありません。

javascript

1document.createElement('<foo>'); // DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('<foo>') is not a valid name.

配列

要求仕様次第ですが、配列の扱いも多分、おかしいです。

console.log(OBJtoXML({array:[1,2,3]})); // <array></array><array></array><array></array><array></array> console.log(OBJtoXML([1,2,3])); // 123

投稿2022/09/17 03:12

think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki_90453

2022/10/06 09:29

ありがとうございます!
guest

0

URLなどに?や&を含んだ場合、XMLの変換が上手くいかず

XMLで&をエスケープしたい場合、&amp;と変換する必要があります。

投稿2022/09/16 08:45

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問