Kan ‘appendChild’ niet uitvoeren op ‘Node’: slechts één element op document toegestaan

Ik probeer een extern svg-bestand te laden en er vervolgens extra SVG-elementen op te schrijven. Als ik dat doe, krijg ik de volgende foutmelding

Kan ‘appendChild’ niet uitvoeren op ‘Node’: slechts één element op document toegestaan

wanneer ik in Chrome inspecteer.

Hier is de HTML:

<html>
  <head>
    <link rel="stylesheet" type="text/css" href="css/index.css">
    <title>Hello World</title>
  </head>
  <body>
      <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="mySvg">
        <circle cx="40" cy="30" r="15" fill="#FF00FF"
          stroke="#000000" stroke-width="2" />
      </svg>
      <object data="img/drawing.svg" type="image/svg+xml"
        align="center" id="svgDrw" height="80vh"></object>
    <script type="text/javascript" src="js/problem.js"></script>
  </body>
</html>

Hier is problem.js:

var svgXtraDoc;
var d = document.getElementById("svgDrw");
d.addEventListener("load",function(){
  // get the inner DOM 
  svgXtraDoc = d.contentDocument;
  // get the inner element by id
  svgRect1 = svgXtraDoc.getElementById("MyRect1");
  svgRect2 = svgXtraDoc.getElementById("MyRect2");
}, false);
function addRect() {
  var svgRect = document.createElementNS("http://www.w3.org/2000/svg", 
    "rect");
  svgRect.setAttribute("x", 100);
  svgRect.setAttribute("y", 100);
  svgRect.setAttribute("width", 100);
  svgRect.setAttribute("height", 100);
  svgRect.style.fill = "red";
  // mySvg.appendChild(svgRect);
  svgXtraDoc.appendChild(svgRect);
}
document.getElementById("mySvg").addEventListener("click", addRect);

… en hier is drawing.svg, ontdaan van een deel van de Inkscape cruft:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   width="29.02857mm"
   height="37.092064mm"
   viewBox="0 0 102.85714 131.42857"
   id="svg2"
   version="1.1">
  <g
     id="layer1"
     transform="translate(-205.71428,-218.07649)">
    <rect
       style="stroke:none;fill-opacity:1;fill:#5eb056"
       id="MyRect1"
       width="102.85714"
       height="131.42857"
       x="205.71428"
       y="218.07649" />
    <rect
       style="fill:#000000;stroke:none;fill-opacity:1"
       id="MyRect2"
       width="42.857143"
       height="65.714287"
       x="231.42857"
       y="252.3622" />
  </g>
</svg>

De fout treedt op wanneer u op de cirkel klikt: de rechthoek die zou moeten verschijnen in de geïmporteerde tekening met twee rechthoeken, verschijnt niet en de foutmelding “Kan ‘appendChild’ niet uitvoeren op ‘Node’: slechts één element op document toegestaan.” wordt weergegeven in de console.

Als ik dit verander zodat de rechthoek wordt toegevoegd aan de svg die de cirkel bevat, d.w.z. door de regel “// mySvg.appendChild(svgRect);”, te verwijderen, wordt de rechthoek met succes weergegeven.

Ik weet ook dat het tekenbestand succesvol wordt geladen, omdat ik in andere code (om redenen van beknoptheid hier niet opgenomen) de kleuren van de rechthoeken in dat bestand kan wijzigen. Het lijkt er dus op dat ik toegang heb tot bestaande elementen in het bestand, maar geen elementen kan toevoegen.

Is er iets met extern geladen SVG’s versus inline SVG’s waar ik geen rekening mee houd?

Nog een laatste ding — dit gaat naar een Cordova-app, dus ik zou het klein willen houden, dus pure JavaScript-oplossingen hebben de voorkeur. Ik gebruik JQuery of SnapSVG als het moet, maar het lijkt erop dat mijn behoeften zo eenvoudig zijn dat het mogelijk zou moeten zijn om dit te doen zonder externe bibliotheken.


Antwoord 1, autoriteit 100%

In mijn geval klaagde de DOM omdat ik probeerde een kind toe te voegen in het document zelf:

document.appendChild(myElement);

Ik heb het opgelost door een verwijzing naar de body-tag te krijgen:

document.body.appendChild(logger);

Antwoord 2, autoriteit 16%

Er is een verschil tussen het hoofdknooppunt van een document en het documentelement. Wat je wilt is het <svg>documentelement, maar .contentDocumentgeeft je het hoofdknooppunt.

Het hoofdknooppunt bevindt zich één hiërarchieniveau hoger. Dit betekent dat het <svg>documentelement zich in het hoofdknooppunt bevindt, en het hoofdknooppunt mag alleen dit ene <svg>onderliggende element hebben.

Doe dit om het documentelement te krijgen:

svgXtraDoc = d.contentDocument.documentElement;

Other episodes