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"];
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);