Yo. Here it is.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace svgcheck
{
class SVGChecker
{
static Dictionary<String, HashSet<String>> dict = new Dictionary<String, HashSet<String>>()
{
{ "a", new HashSet<String>{"class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "id", "mask", "opacity", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "href", "xlink:href", "xlink:title"} },
{ "circle", new HashSet<String>{"class", "clip-path", "clip-rule", "cx", "cy", "fill", "fill-opacity", "fill-rule", "filter", "id", "mask", "opacity", "r", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"} },
{ "clipPath", new HashSet<String>{"class", "clipPathUnits", "id"} },
{ "defs", new HashSet<String>{} },
{ "style" , new HashSet<String>{"type"} },
{ "desc", new HashSet<String>{} },
{ "ellipse", new HashSet<String>{"class", "clip-path", "clip-rule", "cx", "cy", "fill", "fill-opacity", "fill-rule", "filter", "id", "mask", "opacity", "requiredFeatures", "rx", "ry", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"} },
{ "feGaussianBlur", new HashSet<String>{"class", "color-interpolation-filters", "id", "requiredFeatures", "stdDeviation"} },
{ "filter", new HashSet<String>{"class", "color-interpolation-filters", "filterRes", "filterUnits", "height", "id", "primitiveUnits", "requiredFeatures", "width", "x", "xlink:href", "y"} },
{ "foreignObject", new HashSet<String>{"class", "font-size", "height", "id", "opacity", "requiredFeatures", "style", "transform", "width", "x", "y"} },
{ "g", new HashSet<String>{"class", "clip-path", "clip-rule", "id", "display", "fill", "fill-opacity", "fill-rule", "filter", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "font-family", "font-size", "font-style", "font-weight", "text-anchor"} },
{ "image", new HashSet<String>{"class", "clip-path", "clip-rule", "filter", "height", "id", "mask", "opacity", "requiredFeatures", "style", "systemLanguage", "transform", "width", "x", "xlink:href", "xlink:title", "y"} },
{ "line", new HashSet<String>{"class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "id", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "x1", "x2", "y1", "y2"} },
{ "linearGradient", new HashSet<String>{"class", "id", "gradientTransform", "gradientUnits", "requiredFeatures", "spreadMethod", "systemLanguage", "x1", "x2", "xlink:href", "y1", "y2"} },
{ "marker", new HashSet<String>{"id", "class", "markerHeight", "markerUnits", "markerWidth", "orient", "preserveAspectRatio", "refX", "refY", "systemLanguage", "viewBox"} },
{ "mask", new HashSet<String>{"class", "height", "id", "maskContentUnits", "maskUnits", "width", "x", "y"} },
{ "metadata", new HashSet<String>{"class", "id"} },
{ "path", new HashSet<String>{"class", "clip-path", "clip-rule", "d", "fill", "fill-opacity", "fill-rule", "filter", "id", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"} },
{ "pattern", new HashSet<String>{"class", "height", "id", "patternContentUnits", "patternTransform", "patternUnits", "requiredFeatures", "style", "systemLanguage", "viewBox", "width", "x", "xlink:href", "y"} },
{ "polygon", new HashSet<String>{"class", "clip-path", "clip-rule", "id", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "points", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"} },
{ "polyline", new HashSet<String>{"class", "clip-path", "clip-rule", "id", "fill", "fill-opacity", "fill-rule", "filter", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "points", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"} },
{ "radialGradient", new HashSet<String>{"class", "cx", "cy", "fx", "fy", "gradientTransform", "gradientUnits", "id", "r", "requiredFeatures", "spreadMethod", "systemLanguage", "xlink:href"} },
{ "rect", new HashSet<String>{"class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "height", "id", "mask", "opacity", "requiredFeatures", "rx", "ry", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "width", "x", "y"} },
{ "stop", new HashSet<String>{"class", "id", "offset", "requiredFeatures", "stop-color", "stop-opacity", "style", "systemLanguage"} },
{ "svg", new HashSet<String>{"class", "clip-path", "clip-rule", "filter", "id", "height", "mask", "preserveAspectRatio", "requiredFeatures", "style", "systemLanguage", "viewBox", "width", "x", "xmlns", "xmlns:se", "xmlns:xlink", "y"} },
{ "switch", new HashSet<String>{"class", "id", "requiredFeatures", "systemLanguage"} },
{ "symbol", new HashSet<String>{"class", "fill", "fill-opacity", "fill-rule", "filter", "font-family", "font-size", "font-style", "font-weight", "id", "opacity", "preserveAspectRatio", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "viewBox"} },
{ "text", new HashSet<String>{"class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "font-family", "font-size", "font-style", "font-weight", "id", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "text-anchor", "transform", "x", "xml:space", "y"} },
{ "textPath", new HashSet<String>{"class", "id", "method", "requiredFeatures", "spacing", "startOffset", "style", "systemLanguage", "transform", "xlink:href"} },
{ "title", new HashSet<String>{} },
{ "tspan", new HashSet<String>{"class", "clip-path", "clip-rule", "dx", "dy", "fill", "fill-opacity", "fill-rule", "filter", "font-family", "font-size", "font-style", "font-weight", "id", "mask", "opacity", "requiredFeatures", "rotate", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "text-anchor", "textLength", "transform", "x", "xml:space", "y"} },
{ "use", new HashSet<String>{"class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "height", "id", "mask", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "transform", "width", "x", "xlink:href", "y"} },
};
public static bool Check(string url)
{
bool ret = false;
try
{
XmlDocument doc = new XmlDocument();
doc.Load(url);
Console.WriteLine(String.Format("Checking {0}", url));
XmlNodeList nodes = doc.GetElementsByTagName("*");
for (int node_index = nodes.Count - 1; node_index >= 0; node_index--)
{
XmlNode node = nodes[node_index];
String tag = node.Name;
HashSet<String> hset = null;
if (dict.TryGetValue(tag,out hset))
{
for (int attrib_index = node.Attributes.Count -1; attrib_index >= 0; attrib_index--)
{
XmlAttribute attribute = node.Attributes[attrib_index];
if (hset.Contains(attribute.Name) == false)
{
node.Attributes.RemoveAt(attrib_index);
Console.WriteLine(String.Format("\tDeleting attribute {0}", attribute.Name));
}
}
}
else
{
nodes[node_index].ParentNode.RemoveChild(node);
Console.WriteLine(String.Format("Deleting node {0}", tag));
}
}
String newurl = url.Replace(".svg", ".cleaned.svg");
doc.Save(newurl);
ret = true;
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
return ret;
}
}
}
|