1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SVGをネストした場合のouterHTMLでxmlnsが補完された話

Posted at

TL;DR

事象
svgタグをネストした場合に、ネストしているsvgタグに勝手にxmlns=""が付加されていた。(ChromeとFirefoxで再現。Safariは再現しない)

何が起こる?
表示して欲しいsvg(ネストしているsvg)が表示されない。

解決策

  1. ネストするsvgを作るときにちゃんとxmlnsを指定しておく。
  2. 勝手に付加されたxmlns=""を削る。
  3. 事前にsetAttributeでxmlnsを指定してあげる。

はじめに

そもそも何をしたかったのかと言うと、svgでテンプレートを作っておいて、後から作成したsvgをそのテンプレートに埋め込んでダウンロードさせたかった。
svgはネストできるので、問題なくできるだろうと思っていたら意外とハマった、という話の備忘録。

事象

まず、以下のコードをjsfiddleとかで実行すると再現できると思います。(2017/12/28現在のChromeとFirefoxでは再現確認)
本来のコードではちゃんとwidthとかviewboxとか様々指定していますが、今回は事象再現のためだけに簡略化しています。

sample.js
const parser = new DOMParser();
const doc = parser.parseFromString( `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>`, "image/svg+xml" );

const templateSVG = doc.childNodes[ 0 ];
const savingSVG = parser.parseFromString( `<svg></svg>`, "image/svg+xml" ).firstElementChild;

templateSVG.appendChild( savingSVG );

console.log(doc.documentElement.outerHTML);

ChromeかFirefoxで実行した結果、コンソールに出力されるのは以下のような文字列です。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><svg xmlns=""/></svg>

Safariだと以下になります。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><svg/></svg>

差としては、ネストされているsvgの属性に、勝手にxmlns=""が付加されているかどうか。

この状態のsvgをBlobにしてダウンロードして、それを開くとあら不思議。
ネストしたsvgの方だけ表示されない。。。

ちなみに、ネストしている方のsvgを単体で保存した場合にはちゃんと表示されます。

原因と解決策

調べてみると、どうやらタイミング的にはouterHTMLで書き出した時に<svg xmlns=""></svg>といった具合にxmlns=""が補完されていました。

xmlns=""を削れば動きます。
ただ、outerHTMLをすると勝手についてしまうので、ちゃんとsetAttributexmlnsの値を指定してあげました。

これで解決!

const parser = new DOMParser();
const doc = parser.parseFromString( templateString, "image/svg+xml" );
const templateSVG = doc.childNodes[ 0 ];

const partSVG = parser.parseFromString( svgString, "image/svg+xml" ).firstElementChild;

// xmlnsは必須。ない場合はouterHTMLで勝手にxmlns=""が追加され、結果的に表示されない。
partSVG.setAttribute( "xmlns", "http://www.w3.org/2000/svg" );
templateSVG.appendChild( partSVG );

console.log(doc.documentElement.outerHTML);

ただ、そもそも上記のコードでいうところのsvgStringを作る際にxmlnsを指定しておけば良かったという。。。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?