当所需的 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>
所以在这种最常见的情况下,我试图获取 polyline
的 points
属性的值。我确定这将是一个简单的 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
。
我正在 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>
所以在这种最常见的情况下,我试图获取 polyline
的 points
属性的值。我确定这将是一个简单的 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
。