Home > Blockchain >  Inserting new elements in the end of an svg file
Inserting new elements in the end of an svg file

Time:07-22

I have an svg file in which I would like to insert, say, a circle, using c# and XPath :

This is the file content before:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="594.75pt" height="841.5pt" viewBox="0 0 594.75 841.5" style="border: 1px solid red">
<circle cx="50%" cy="50%" r="50" fill="red" />
</svg>

I would like this file content after:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="594.75pt" height="841.5pt" viewBox="0 0 594.75 841.5" style="border: 1px solid red">
<circle cx="50%" cy="50%" r="50" fill="red" />
<circle stroke="blue" stroke-width="3" cx="148.63pt" cy="401.02pt" r="84.15" fill-opacity="0.1"/> 
</svg>

I'm using the following code:

XmlDocument doc = new XmlDocument();
doc.Load(@"D:\\test.svg");

XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(doc.NameTable);
xmlnsManager.AddNamespace("xlink", "http://www.w3.org/1999/xlink");
xmlnsManager.AddNamespace("svg", "http://www.w3.org/2000/svg");

XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment();
xmlDocFrag.InnerXml = @"<circle stroke=\"blue\" stroke-width=\"3\" cx=\"148.63pt\" cy=\"401.02pt\" r=\"84.15\" fill-opacity=\"0.1\"/>";

XmlElement mapElement = (XmlElement)doc.SelectSingleNode(@"//svg[last()]", xmlnsManager);
mapElement.AppendChild(xmlDocFrag);  // <----- null !!

doc.Save(path);

However, mapElement is null after SelectSingleNode :( I expected it to be the existing circle element.

CodePudding user response:

The reason you are getting null is because you are not adding the namespace alias defined in xmlnsManager to your XPath.

XmlElement mapElement = (XmlElement)doc.SelectSingleNode(@"//svg:svg[last()]", xmlnsManager);

Or more simply

XmlElement mapElement = (XmlElement)doc.SelectSingleNode(@"/svg:svg", xmlnsManager);

You don't even need XPath at all

XmlElement mapElement = (XmlElement)doc["svg"];

dotnetfiddle


It seems much easier to just use the newer XDocument and XElement classes

var xDoc = XDocument.Load(path);
var xmlns = xDoc.Root.GetDefaultNamespace();
xDoc.Root.Add(new XElement(xmlns   "circle",
                        new XAttribute("stroke","blue"),
                        new XAttribute("stroke-width","3"),
                        new XAttribute("cx","148.63pt"),
                        new XAttribute("cy","401.02pt"),
                        new XAttribute("r","84.15"),
                        new XAttribute("fill-opacity","0.1")
                          )
             );

xDoc.Save(path);

dotnetfiddle

  • Related