Does Svg Xmlns Attribute Value Requires Protocol? Can It Be Https or Relative

Does svg xmlns attribute value requires protocol? Can it be https or relative?

It's not really a URL, it's a namespace that simply happens to look like a URL. As such it must be written exactly as

xmlns="http://www.w3.org/2000/svg"

omitting the http or changing it to https will not work.

The fact that the namespace contains http does not mean in any way that the SVG file will use the http protocol for any kind of communication. The w3c could have defined the SVG namespace as foo in which case we'd all be writing xmlns="foo" and you'd not even be asking such questions.

Are SVG parameters such as 'xmlns' and 'version' needed?

All user agents (browsers) ignore the version attribute, so you can always drop that.

If you embed your SVG inline in a HTML page and serve that page as text/html then xmlns attributes are not required. Embedding SVG inline in HTML documents is a fairly recent innovation that came along as part of HTML5.

If however you serve your page as image/svg+xml or application/xhtml+xml or any other MIME type that causes the user agent to use an XML parser then the xmlns attributes are required. This was the only way to do things until recently so there is a lot of content served like this.

svg creates http instead https on non-absolute URL

The problem was caused by some caching in the browser (Firefox). After clearing the cache and restarting the browser the image is downloaded with HTTPS.

Requested: https://www.w3.org/2000/svg Found: http://www.w3.org/2000/svg

Don't change the URLs for namespace definitions. These are the attributes starting with xmlns, optionally followed by a : and a more detailed name.

For SVG, the namespace must be http://www.w3.org/2000/svg, see the specification.

These URLs are not used for connecting to, they just define what the elements mean (see XML Namespaces), so you're not gaining any security by changing them. Instead you're just making your SVG file invalid.

XML Namespace URI with HTTPS?

The URI is the namespace name, which identifies the namespace.

While, in case of some URI schemes (like http, https, ftp etc.), it would be possible to provide the schema (or other related information), this is "not a goal":

It is not a goal that it be directly usable for retrieval of a schema (if any exists).

(Most URI schemes wouldn’t allow this to begin with, e.g., urn, tag, jabber etc.)

You should specify the URI exactly as documented, as this is what consumers expect and look for (most consumers probably never try to actually retrieve the URI), and XML Names 1.0 is pretty strict about comparing URIs.

All these would be different namespace names, even if they would resolve to the same Web document:

http://www.springframework.org/schema/security
http://www.Springframework.org/schema/security
httP://www.springframework.org/schema/security
http://www.springframework.org/schema/Security
https://www.springframework.org/schema/security
https://www.springframework.ORG/schema/security

How do I save/export an SVG file after creating an SVG with D3.js (IE, safari and chrome)?

There are 5 steps. I often use this method to output inline svg.

  1. get inline svg element to output.
  2. get svg source by XMLSerializer.
  3. add name spaces of svg and xlink.
  4. construct url data scheme of svg by encodeURIComponent method.
  5. set this url to href attribute of some "a" element, and right click this link to download svg file.

//get svg element.
var svg = document.getElementById("svg");

//get svg source.
var serializer = new XMLSerializer();
var source = serializer.serializeToString(svg);

//add name spaces.
if(!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){
source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
}
if(!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){
source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
}

//add xml declaration
source = '<?xml version="1.0" standalone="no"?>\r\n' + source;

//convert svg source to URI data scheme.
var url = "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(source);

//set url value to a element's href attribute.
document.getElementById("link").href = url;
//you can download svg file by right click menu.

How to reference external SVG file in SVG correctly?

This answers the original question, but attempts to answer the matter of referencing external SVG files in SVG in broader terms, too.

Lack of SVG support

Six years later, Chrome and Safari still do not allow for the referencing/loading of external SVG files.

This is why <use xlink:href="another.svg#rectangle" class="blue"/> works in Firefox, but not in WebKit browsers.

All in one file

If the project can afford it, simply put all of the SVG files in one parent HTML or SVG file. This way, it'll work in all three browsers:

  • Example 1 · Both SVGs in one file (SVG)
  • Example 2 · Both SVGs in one file (HTML)

But then, it's not really external, granted!

To benefit from caching and avoid repeating oneself, we'd like to keep repeatable SVG content in an external file.

Work around: insert the external SVG file via JavaScript

Keep the styles and definitions in one SVG file, keep the SVG geometry in some other file, and simply load the former from the latter via JavaScript.

In pure SVG and pure JavaScript

Define what we'd like to be able to use. styles-and-defs.svg:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css" >
<![CDATA[

.blue { fill: blue; }

]]>
</style>

<defs>
<rect id="rectangle" class="blue" width="50" height="50" />
</defs>
</svg>

Use the geometry created above, and load its definition. parent.svg:

<svg version="1.1"
baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
width="420" height="120">

<use xlink:href="#rectangle" x="10" y="10" />

<script><![CDATA[

/** When the document is ready, this self-executing function will be run. **/
(function() {

var ajax = new XMLHttpRequest();
ajax.open("GET", "styles-and-defs.svg", true);
ajax.send();

/**
* Append the external SVG to this very SVG.
*
* Notice the use of an SVG selector on the document derived from the AJAX result.
* This is because the full document cannot be included directly into the SVG.
* Trying to include to do so would result in:
* `HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy` in Firefox;
* `Nodes of type '#document' may not be inserted inside nodes of type 'svg'.` in Chrome.
*/
ajax.onload = function(e) {
var parser = new DOMParser();
var ajaxdoc = parser.parseFromString( ajax.responseText, "image/svg+xml" );
document.getElementsByTagName('svg')[0].appendChild( ajaxdoc.getElementsByTagName('svg')[0] );
}

})(); /* END (anonymous function) */

]]></script>
</svg>

This answers the OP.

In HTML

Same basic approach as in pure SVG:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
Load external SVG (HTML)
</title>
<meta name="author" content="Fabien Snauwaert">
</head>

<body>

<svg version="1.1"
baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
width="420" height="120">
<use xlink:href="#rectangle" x="10" y="10" />
</svg>

<script>

/** When the document is ready, this self-executing function will be run. **/
(function() {

var ajax = new XMLHttpRequest();
ajax.open("GET", "styles-and-defs.svg", true);
ajax.send();

/**
* Append the external SVG to this very SVG.
*
* Notice the use of an SVG selector on the document derived from the AJAX result.
* This is because the full cannot be included directly into the SVG.
* Trying to include to do so would result in:
* `HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy` in Firefox;
* `Nodes of type '#document' may not be inserted inside nodes of type 'svg'.` in Chrome.
*/
ajax.onload = function(e) {
var parser = new DOMParser();
var ajaxdoc = parser.parseFromString( ajax.responseText, "image/svg+xml" );
document.getElementsByTagName('body')[0].appendChild( ajaxdoc.getElementsByTagName('svg')[0] );
}

})(); /* END (anonymous function) */

</script>

</body>
</html>

You could of course use jQuery (or why not the excellent D3.js) to load the file instead.

Remarks

  • Mind the use of <defs>. I believe this is the nice thing about having an external SVG, you can keep everything neat and organized. (And without it, we'd be displaying the content twice.)
  • I got rid of style.css and simply put the CSS inside of the styles-and-defs file.
  • If, in the HTML version, you observe a gap between the parent SVG and the window borders, this is because the "invisible" SVG (with the styles and definition), like any other SVG, is an inline element. To get rid of this gap, simply set style="display: block;" on that SVG.
  • Download all examples here.

SVG is great but can appear to be too little supported, while it does allow for some great things. I hope this helps some folks out there.

Tested OK on OS X 10.12.6 in:

  • Firefox 59.0.2
  • Chrome 66.0.3359.139
  • Safari 11.0.1


Related Topics



Leave a reply



Submit