问题描述
我写在C#程序基本上读取SVG文件,并做一些有用的东西的内容。最复杂的数据我将与合作的路径。他们采取的形式,如这样的:
I am writing a program in C# which essentially reads an SVG file, and does some useful things with the contents. The most complex data I will be working with are paths. They take forms such as this:
<path d="M5.4,3.806h6.336v43.276h20.738v5.256H5.4V3.806z"/>
在这种情况下,M,H,V,H,V,和z表示一些命令。在某种程度上,他们就像功能,具有以下这些数字是参数。也有一些更复杂的:
In this case, the M, h, v, H, V, and z indicate some commands. In a way they are like functions, with the numbers following them being arguments. There are also some more complex ones:
<path d="M70.491,50.826c-2.232,1.152-6.913,2.304-12.817,2.304c-13.682,0-23.906-8.641-23.906-24.626
c0-15.266,10.297-25.49,25.346-25.49c5.977,0,9.865,1.296,11.521,2.16l-1.584,5.112C66.747,9.134,63.363,8.27,59.33,8.27
c-11.377,0-18.938,7.272-18.938,20.018c0,11.953,6.841,19.514,18.578,19.514c3.888,0,7.777-0.792,10.297-2.016L70.491,50.826z"/>
在这种情况下,c的命令被随后6个参数(-2.232,1.152, - 6.913,2.304,-12.817,并且在第一壳体2.304)。你可以看到这是如何可能很麻烦。我的问题是这样的:是SO社会认识的任何现有的库读取这些数据到一些有用的ADT
In this case, the "c" command is followed by 6 arguments (-2.232, 1.152, -6.913, 2.304, -12.817, and 2.304 in the first case). You can see how this can get tricky. My questions is this: is the SO community aware of any existing libraries that read such data into some useful ADTs?
在我走了编码的一切,写一吨的字符串?解析功能,我真的想不重新发明轮子。此外,任何建议,将不胜感激。我知道如何读取XML文档,这是不是这里的问题。
Before I go off coding everything and writing a ton of string parsing functions, I'd really like to not re-invent the wheel. Also, any advice would be appreciated. I am aware of how to read an XML document, that isn't the issue here.
推荐答案
我不知道在C#中特定的库,但是你可以通过分析这种结构是这样开始:
I don't know of specific libraries in c#, however you could start by parsing this kind of structure like this:
string path = "M5.4,3.806h6.336v43.276h20.738v5.256H5.4V3.806z";
string separators = @"(?=[MZLHVCSQTAmzlhvcsqta])"; // these letters are valid SVG
// commands. Whenever we find one, a new command is
// starting. Let's split the string there.
var tokens = Regex.Split(path, separators).Where(t => !string.IsNullOrEmpty(t));
现在你有命令之后它们的参数列表。然后,您可以继续以同样的方式分裂的参数。
now you have a list of commands followed by their arguments. You could then proceed to split the arguments in the same way.
您说,这个论点可以用空格,逗号或减号(被剥离,不像逗号和空格,应保持的参数的一部分),所以你可以使用另一种简单的regex(请注意,我不是正则表达式的球迷,但在这种情况下,我认为他们增加可读性)。
You said the arguments can be separated by a space, a comma or a minus sign (which,unlike the comma and the whitespace, should remain part of the arguments), so you can use another simple regex (note that I'm no fan of regular expressions, but in this case I think they add to readability).
string argSeparators = @"[\s,]|(?=-)"; // discard whitespace and comma but keep the -
var splitArgs = Regex
.Split(remainingargs, argSeparators)
.Where(t => !string.IsNullOrEmpty(t));
我把这个包在SVGCommand类,像这样
I would wrap this in a SVGCommand class, like this
class SVGCommand
{
public char command {get; private set;}
public float[] arguments {get; private set;}
public SVGCommand(char command, params float[] arguments)
{
this.command=command;
this.arguments=arguments;
}
public static SVGCommand Parse(string SVGpathstring)
{
var cmd = SVGpathstring.Take(1).Single();
string remainingargs = SVGpathstring.Substring(1);
string argSeparators = @"[\s,]|(?=-)";
var splitArgs = Regex
.Split(remainingargs, argSeparators)
.Where(t => !string.IsNullOrEmpty(t));
float[] floatArgs = splitArgs.Select(arg => float.Parse(arg)).ToArray();
return new SVGCommand(cmd,floatArgs);
}
}
现在一个简单的解释可能是这个样子
Now a simple "interpreter" could look something like this:
string path = "M70.491,50.826c-2.232,1.152-6.913,2.304-12.817,2.304c-13.682,0-23.906-8.641-23.906-24.626" +
"c0-15.266,10.297-25.49,25.346-25.49c5.977,0,9.865,1.296,11.521,2.16l-1.584,5.112C66.747,9.134,63.363,8.27,59.33,8.27" +
"c-11.377,0-18.938,7.272-18.938,20.018c0,11.953,6.841,19.514,18.578,19.514c3.888,0,7.777-0.792,10.297-2.016L70.491,50.826z";
string separators = @"(?=[A-Za-z])";
var tokens = Regex.Split(path, separators).Where(t => !string.IsNullOrEmpty(t));
// our "interpreter". Runs the list of commands and does something for each of them.
foreach (string token in tokens){
// note that Parse could throw an exception
// if the path is not correct
SVGCommand c = SVGCommand.Parse(token);
Console.WriteLine("doing something with command {0}", c.command);
}
如果你需要做一些更复杂,F#是可能的(并且是用C#互操作)。我不建议学习F#只为这个特定的任务,我想我要提到它,如果你已经寻找到它的东西。
If you need to do something more sophisticated, F# is probably better suited for the job (and is interoperable with C#). I'm not suggesting to learn F# just for this specific task, I just thought I'd mention it, in case you are already looking into it for something else.
这篇关于解析SVG"路径"用C#元素 - 是否有库都来做到这一点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!