如果在运行时之前不知道所需的XElement名称,如何从XDocument获取属性值?

时间:2017-02-14 18:09:35

标签: c# svg xamarin.forms linq-to-xml

我正在使用Xamarin.Forms中的SVG文件。这些文件非常简单,包含一个形状,其形状通常为polyline。但是,有些边缘情况可能存在其他几种基于点的形状之一。在解析这些文件时,我试图获取shape元素上特定属性的值。

这是我希望解析的一个例子:

<svg width="1200" height="800" version="1.1" bordercolor="#666666" borderopacity="1.0" xmlns="http://www.w3.org/2000/svg">
    <polyline stroke="#004976" fill="transparent" stroke-width="5" points="479,91 ..." />
</svg>

因此,在这种最常见的情况下,我试图获取points的{​​{1}}属性的值。我确信这将是一个简单的LINQ-to-XML函数,但我很想念它。这是我到目前为止所尝试的内容:

polyline

我已尝试过多个版本,但在每种情况下public static Point[] GetPointsFromSVG(XDocument svg) { XElement shape = svg.Descendants().First(); string pointsValue = shape.Attribute("points").Value; var points = pointsValue.Split(' ').Select(x => x.Split(',')) .Select(y => new Point(int.Parse(y[0]), int.Parse(y[1]))) .ToArray(); return points; } 都是shape,即使null对象有效且格式正确。另请注意,我没有嫁给这种方法,我只需要一些有用的东西!

2 个答案:

答案 0 :(得分:2)

如果您期望恰好1个“点”属性,那么您只需搜索所有后代的名称:

var xmlString = @"<svg width=""1200"" height=""800"" version=""1.1"" bordercolor=""#666666"" borderopacity=""1.0"" xmlns=""http://www.w3.org/2000/svg"">
    <polyline stroke=""#004976"" fill=""transparent"" stroke-width=""5"" points=""479,91 ..."" />
</svg>";

var pointsValue = XDocument.Parse(xmlString)
    .Descendants()
    .Attributes("points")
    .Single()
    .Value;

如果集合中有零个或多个元素,Single()将抛出异常。或者,您可以通过所有.Single()结果删除foreach.Descendants().Attributes("points")

答案 1 :(得分:1)

您只是遗漏了一件事 - 当您执行svg.Descendants().First()时,它会为您提供文档的第一个后代,即svg元素。

相反,请svg.Root.Descendants().First(),甚至svg.Root.FirstNode as XElement

string svgString = @"<svg width='1200' height='800' version='1.1' bordercolor='#666666' borderopacity='1.0' xmlns='http://www.w3.org/2000/svg'>
    <polyline stroke='#004976' fill='transparent' stroke-width='5' points='479,91 ...' />
</svg>";
var svg = XDocument.Parse(svgString);
XElement shape = svg?.Root?.FirstNode as XElement;

if (shape == null) return null;

string pointsValue = shape.Attribute("points").Value;

var points = pointsValue.Split(' ').Select(x => x.Split(','))
                        .Select(y => new Point(int.Parse(y[0]), int.Parse(y[1])))
                        .ToArray();


Console.ReadKey();

请注意,由于SVG属性中的“...”,这将导致异常,这不会很有效....还要注意,您的值很可能最终成为小数/双精度/浮点数,不是整数(例如points='479.994,91.2223 ....'