当所需的 XElement 名称直到运行时才知道时,如何从 XDocument 获取属性值?

How to get an attribute value from XDocument when the required XElement name is not known until runtime?

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

这是我希望解析的示例:

<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>

所以在这种最常见的情况下,我试图获取 polylinepoints 属性的值。我确定这将是一个简单的 LINQ-to-XML 函数,但我错过了它。到目前为止,这是我尝试过的:

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,即使 XDocument 对象有效且格式正确。另请注意,我不喜欢这种方法,我只需要有用的东西!

您只是遗漏了一件事 - 当您执行 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 属性中的“...”,这将无法正常工作,这将导致异常...。另请注意,您的值很可能最终成为 decimals/doubles/floats,不是整数(例如 points='479.994,91.2223 ....'

如果您正好需要 1 个 "points" 属性,那么您可以只搜索该名称的所有后代:

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() 将抛出异常。或者您可以删除所有 .Descendants().Attributes("points") 结果中的 .Single()foreach