'how to save/ export inline SVG to svg

I am currently trying to save an animated SVG as a viewable svg from inline code, My application allows the user to apply a number of set animations to the SVG, The user should then be able to save the animated SVG to their local machine and view the animated SVG.

However, when I open the downloaded SVG file I am getting this error

"This page contains the following errors: error on line 4 at column 9: Extra content at the end of the document Below is a rendering of the page up to the first error."

Here is the code that is currently being downloaded:

  <rect id="background" width="100" height="120" style="fill:black;  stroke-width:1;
stroke:black"></rect>
        <g id="ghost" transform="rotate(0), translate(0,0), scale   (1.0)">
            <path id="body" d="M     10  120     A   2.0     5.8,    0   0   1,  90  120" style="stroke:white;   strokewidth:0.5;   fill:white"></path>
            <g id="eyes" transform="rotate(0,50,40),    translate(0,0)">
                <g id="eye-l" transform="rotate(0,50,40),   translate(0,0)">
                    <ellipse id="eye-l-ball" cx="45" cy="40" rx="4" ry="6" style="stroke:black;
fill:black;"></ellipse>
                    <rect transform="rotate(16,46,35)" x="40" y="33" width="11" height="6" fill="white" visibility="hidden"></rect>
                    <g id="eye-l-brow">
                        <path d="M   41  32  Q   45  27  49  32" stroke="black" stroke-width="0.5" fill="transparent"></path>
                        <path d="M   41  32  Q   45  26  49  32" stroke="black" stroke-width="0.5" fill="transparent"></path>
                    </g>
                </g>
                <g id="icon" transform="rotate(0,50,40),    translate(0,0)">
                    <g>
                        <ellipse class="st1 left-eye" cx="45" cy="40" rx="4" ry="6" stroke="orange"></ellipse>
                        <ellipse class="st1 right-eye" cx="1409.8" cy="1304.6" rx="41.1" ry="61.7" stroke="black"></ellipse>

                <g id="eye-r" transform="rotate(0,50,40),   translate(0,0)">
                    <ellipse id="eye-r-ball" cx="55" cy="40" rx="4" ry="6"></ellipse>
                    <rect transform="rotate(-16,56,35)" x="49" y="32" width="11" height="6" fill="white" visibility="hidden"></rect>
                </g>
                <g id="eye-l-brow">
                    <path d="M   51  32  Q   55  27  59  32" stroke="black" stroke-width="0.5" fill="transparent"></path>
                    <path d="M   51  32  Q   55  26  59  32" stroke="black" stroke-width="0.5" fill="transparent"></path>
                </g>
            </g>
        </g>
            </g>
        </g>
    <!-- Draw the square path (circle will move around this path) -->
    <!-- <path fill="none" stroke="silver" d="M 10 10 H 90 V 90 H 10 L 10 10"/> -->

    <!-- Draw a 5px radius red circle - this will be animated -->
    <!--   <circle r="5" fill="red"> -->

    <!-- Animation One - Move Circle along square path -->
    <!--    <animateMotion id="theCirclePath" dur="5s" repeatCount="indefinite"
         path="M 10 10 H 90 V 90 H 10 L 10 10" /> -->

    <!-- Animation Two - Change Circle Radius Size -->
    <!--    <animate id="theCircleSize" dur="10s" repeatCount="indefinite"
         attributeName="r" values="5;10;5"/>
    </circle>
    -->

So it appears to be missing the SVG tags.

Please see my code below, The function for saving the SVG starts on line 154.

<html>

<head>
  <title>Animated SVG</title>

  <style>
    .myDisplayBox {
      border: 1px solid black;
      font-family: "Lucida Console", "Courier New", monospace;
      color: white;
      height: 500px;
      width: 400px;
      background-color: grey;
      padding: 10px;
      margin: 10 auto;
    }

    .mySVGBox {
      height: 250px;
      width: 400px;
      border: 1px solid black;
      margin: auto;
      margin-top: 10px;
      padding: 10px;
    }

    #myDisplayBoxTitle {
      font-family: Arial, Helvetica, sans-serif;
      font-weight: bold;
      font-size: 16pt;
      text-align: center;
      color: black;
      margin: 10 auto;
    }

    h1 {
      font-family: Arial, Helvetica, sans-serif;
      text-align: center;
    }

    svg,
    object {
      border: 1px solid grey;
      display: block;
      margin: auto;
    }

    .button {
      border: none;
      color: white;
      padding: 13px 39px;
      text-align: center;
      text-decoration: none;
      display: inline-block;
      font-size: 14px;
      margin: 4px 2px;
      cursor: pointer;
    }

    .butGreen {
      background-color: #4CAF50;
    }

    .butBlue {
      background-color: #008CBA;
    }
  </style>

  <script type="text/javascript">
  </script>
</head>

<body>
  <h1>Playing with an Animated SVG</h1>

  <div class="mySVGBox">
    <h1>Inline SVG Content</h1>
    <svg id="mySVGInline" width="100" height="100" xmlns="http://www.w3.org/2000/svg">

      <!-- Draw the square path (circle will move around this path) -->
      <path fill="none" stroke="silver" d="M 10 10 H 90 V 90 H 10 L 10 10"/>

      <!-- Draw a 5px radius red circle - this will be animated -->
      <circle r="5" fill="red">

         <!-- Animation One - Move Circle along square path -->
         <animateMotion id="theCirclePath" dur="5s" repeatCount="indefinite"
           path="M 10 10 H 90 V 90 H 10 L 10 10" />

         <!-- Animation Two - Change Circle Radius Size -->
         <animate id="theCircleSize" dur="10s" repeatCount="indefinite"
           attributeName="r" values="5;10;5"/>
      </circle>
    </svg>
    <br />
    <button class="button butGreen" onclick="saveSVG();">SAVE</button>
    <button class="button butGreen" onclick="updateSVGContent();">UPDATE</button>
    <button class="button butGreen" onclick="displaySVG();">DISPLAY</button>
  </div>

  <div id="myDisplayBoxTitle"></div>
  <div id="myXMLDisplay" class="myDisplayBox"></div>


  <script type="text/javascript">
    //
    // REFERENCING THE SVG
    //

    // get reference to the inline SVG
    var svgInline = document.getElementById('mySVGInline');
    // console.log(svgInline);


    //
    // REFERENCING ELEMENTS
    //

    // inline reference
    //var element = document.getElementById('circle');
    // move the selected inline element 50px to right
    //var cx = parseFloat(element.getAttributeNS(null, 'cx'));
    //element.setAttributeNS(null, 'cx', cx + 50);

    //
    // BUTTON FUNCTIONS
    //

    // update SVG animation
    function updateSVGContent() {
      var circlePath = document.getElementById("theCirclePath");
      var duration = "dur";
      var current = circlePath.getAttributeNS(null, duration);
      // toggle from 5s to 20s and visa versa
      if (current == "5s") {
        current = "20s"
      } else {
        current = "5s"
      }
      circlePath.setAttributeNS(null, duration, current);
    }

    // display the SVG as XML to the display box
    function displaySVG() {
      var header = "<svg width=\"100\" height=\"100\" xmlns=\"http://www.w3.org/2000/svg\">";
      var footer = "</svg>";
      var displayBox = document.getElementById('myXMLDisplay');
      displayBox.textContent = header + svgInline.innerHTML + footer;
      document.getElementById('myDisplayBoxTitle').innerHTML = "Inline SVG!";
    }


    // save (download) the SVG content from the display box
    function saveSVG() {
        var a = document.body.appendChild(
            document.createElement("a")
        );
        a.download = "export.svg";
        a.href = "data:image/svg+xml," + document.getElementById("mySVGInline").innerHTML;
        a.click();
    }

  </script>



</body>

</html>


Solution 1:[1]

You could include the parent svg by selecting outerHTML:

function saveSVG() {
    var a = document.body.appendChild(
        document.createElement("a")
    );
    let svgCode = document.getElementById("mySVGInline").outerHTML;
    a.download = "export.svg";
    a.href = "data:image/svg+xml," + svgCode;
    a.click();
}

You should also consider to add some additional encoding/escaping. Css tricks: Optimizing SVGs in data URIs

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 herrstrietzel